Modifying anything that extends the View class from inside a thread is bound to fail. This is very common in any widget/UI SDK and Google brilliantly provided us with a few options.
The first one - that I will not talk about much - is Activity.runOnUIThread. Just create a class extending Runnable and call this method. If the current thread is not the UI thread, the runnable will be posted to the main thread event queue and processed later. So DON'T abuse this call or you may overwhelm the main thread.
A much more flexible and interesting approach is to use AsyncTask, which allows you to neatly organize code that must run asynchronously an in the main (UI) thread.
Again you'll have to create your on class extending AsyncTaks with 3 generic types: Parameters, Progress and Result.
The most common use of your class would be:
- override the method doInBackground implementing all that stuff that has to happen in background;
- override onPostExecute implementing the code that MUST run in the UI thread
- Call execute(Params...) to start the task;
For instance:
public class CalculateMD5 extends AsyncThread<String, int, String>{
@Override
protected String doInBackground(String... filename){
// running in background
// calculate md5 of files
...
}
@Override
protected onPostExecute(String result){
// running in the UI thread
myTextView.setText("MD5: "+result);
}
}
if you wan to display the progress to the user, call publishProgress from doInBackground and override the method onProgressUpdated, which also runs in the UI thread.
public class CalculateMD5 extends AsyncThread<String, int, String>{
@Override
protected String doInBackground(String... filename){
// running in background
// calculate md5 of files
publishProgress(number_of_bytes_processed/total_bytes);
...
}
@Override
protected onPostExecute(String result){
// running in the UI thread
myTextView.setText("MD5: "+result);
}
@Override
protected void onProgressUpdate(int... progress){
//% processed ...
}
}
and last but nor least, if you need to prepare things before the background processing starts, override onPreExecute, another method that runs in the UI thread.
You must start the task from the UI thread.
You should always check if the task is not cancelled in your doInBackground method. Use isCancelled for that.
Simple isn't it? So recaping what runs where:
- UI Thread
- onPreExecute
- onProgressUpdate
- onPostExecute
- onCancelled
- Backgroun thread
- doInBackground
---
Programming tricks and tips for android developers
Programming tricks and tips for android developers