Pages

Monday, February 1, 2016

Android Thread vs Handler/Runnable vs AsyncTask

There are several ways to use these classes. I do like this:

1) Handler/Runnable:

new Handler().post(new Runnable() {
    @Override    public void run() {
        ...
    }
});

  • The code runs on UI thread, therefore it can access Views. 
  • If you put a breakpoint inside the run method, the UI will be frozen, so this code can freeze UI and cause ANRs. 
Currently i don't see any real advantage of using a Handler.

2) Thread:

new Thread(new Runnable() {
    @Override    public void run() {
        ...
    }
}).start();

  • Runs in background thread. Accessing views will throw an exception. 
  • When stopped on breakpoints inside run() the UI is operational.
Views can be accessed like this from inside the run method (this particular code is from a Fragment, thats why there is a getActivity() in front. From an Activity just call runOnUiThread): 

getActivity().runOnUiThread(new Runnable() {
    @Override    public void run() {
        ...
    }
});

Code inside run() runs on UI thread. 

This is the way to go, when performance is at stake. For example IO operations and ect.

3) AsyncTasks:

  1. You create a class that  extends AsyncTask
  2. Implement doInBackground and onPostExecute (if needed) methods
  3. I usually use a constructor to pass needed variables.
Then you invoke your AsyncTask: 
new MyAsyncTast(param1).execute();

What happens here:
  • The doInBackground methods runs on separate thread, exactly like the Thread's run();
  • The onPostExecute method runs on UI thread, just like if you call runOnUiThread with a Thread approach.
As I understand AsyncTask is the same as using the new Thread approach. You could actually create your own AsyncTask class by using the new Thread methods. 

Advantages of using AsyncTask is reusability. If the code runs only in one place, then i'd use Thread.
A disatvantage is a bit harder way of getting back to calling activity. For example to call a View's method inside onPostExecute you have invent some additional logic, if compared to Thread method.

What you can do here:

  1. Pass an activity instance and call a public method. (Not the best way)
  2. Pass an activity that implements an interface, and overrides needed methods.
  3. The callback method: as a parameter pass an abstract class, and implement needed methods. Something like this:
The Callback class:

public abstract class CustomCallback {

    public void successCallback(){

    }
}


The AsyncTask call:


new AsyncDBSizeManager(param1, new CustomCallback(){
    @Override    public void successCallback() {
        ...
    }
}).execute();


Then call the callback from onPostExecute:


customCallback.successCallback();



No comments:

Post a Comment