Sunday, August 12, 2012

Asyncronous tasks in android

Hi there, in this entry I'm going to talk about the famous AsyncTasks.

If you want to do some process that could take a while (like download something) and you are using the User Interface thread to do that, your UI will be blocked while doing that process, and that is very annoying for the user. That's not a good design. When the application is doing some process at least it should show some kind of information about what is happening, like a progress dialog showing how long it will take. To do that we have to use threads so while the UI is showing something, the thread is doing his work and updating the UI (for example with the percentage of the process or adding information).

The problem in Android is that the UI thread doesn't allow calls from other threads (for security matters?). So if you are in other thread and you need to update something you cannot simply call a method.

There are some methods to do this (use a Handler, runOnUiThread, AsyncTask) but the most used is AsyncTask because is simple and easy.

An AsyncTask uses three generic types

public class MyAsyncTask extends AsyncTask<Params, Process, Result>  

Params is the type of data that we are going to pass to the task.
Process is the type of data that we are going to pass to the update process method.
Result is the type of data that the task is going to return.

If we are not going to use one of them we have to use the Void type.

The AsynkTask has one method that you have to override

protected Object doInBackground(Object... params) 

This method is launched in other thread. Here we have to do the long process.

The other methods that you can override will help you to update information between threads. They are

@Override
 protected void onPostExecute(Object result) {
  
 }

 @Override
 protected void onPreExecute() {
  
 }

 @Override
 protected void onProgressUpdate(Object... values) {
  
 }

 @Override
 protected void onCancelled() {

 }

onPreExecute is executed before doInBackground and you can use it for make some changes to UI, like show a dialog or disable some views.

onProgressUpdate is the method used to update the progress. It will be called from doInBackground.

onPostExecute will be executed once finished doInBackground. We can use it to dismiss the dialog or to update the information in the UI.

onCancelled will be executed if the task is cancelled.

Knowing how AsyncTask works we can make an asyncronous task that download information from a REST resource to take advantage of the example in the former entry.

We are not going to use the onProgressUpdate method in this example, and we have to pass the URI (a String) to access to the REST service and the task will return the information in a String.

public class MainTwitterClientActivity extends Activity implements OnClickListener{
 private static final String URI = "http://twitter.com/statuses/user_timeline.json?id=xxxxxx";
 private HttpRestConnector restConnector;
 
 private TextView text;
 private Button buttonSend;
 
 
 
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        restConnector = new HttpRestConnectorJson();
        
        buttonSend = (Button) findViewById(R.id.button1);
        
        text = (TextView) findViewById(R.id.editText1);
        
        buttonSend.setOnClickListener(this);
  
    }



 public void onClick(View v) {
  
  new DialogProgressTask(this).execute(URI);
  
 }
 
 public void setText(String t){
  text.setText(t);
 }
    
 private class DialogProgressTask extends AsyncTask{
  private ProgressDialog dialog;
  private Context context;
 
  
  public DialogProgressTask(Context context){
   this.context = context;
  }
  @Override
  protected void onPreExecute() {
   dialog = ProgressDialog.show(this.context, "Downloading", "Downloading information from Twitter...",true);
  }

  @Override
  protected String doInBackground(String... uri) {
   
   return JsonParserTwitter.getInfFromArray(restConnector.execGetConnection(uri[0]));
  }

  
  @Override
  protected void onPostExecute(String result) {
   
   dialog.dismiss();
   setText(result);   
  }

 }

}


In the doInBackground method we just call the REST service using the custom class RestConnector and pass the result to a JSON parser class to get the information in String. Then we use this String in onPostExecute method to call the method "setText" to update the UI showing the information downloaded.

As we can see AsyncTask is simple and very useful.

No comments:

Post a Comment