Archive for January, 2012

Along the years developers came up with different solutions to managing application multi threading requirements. The rule of thumb is to move everything to the background and only perform UI related operations in the Android application UI thread.

It sounds easier than it it, lots of calls seem innocent but affect performance in unpredictable ways. Android has several classes within the framework to help developers to move operations to the background. The main problem is that all of them still require developers to have a solid knowledge about multi threading.

The AsyncTask class has been available since API level 3 and has been over used for quite a long time. It’s miss usage causes several problems with regards to memory leaks and attempts to access UI elements once completed after the Activity has been destroyed while the execution was being performed in the background.

Lets take a look at a typical usage of AsyncTask bellow:

public class AsyncTaskActivity extends AbstractTestActivity {

 protected void onComplexMathButtonClicked() {
     new AsyncTask() {
         @Override
         protected Double doInBackground(Double... params) {
             try {
                 Thread.sleep(3000); // A long complex calculation...
             } catch (InterruptedException e) {
                // Nothing to do here...
             }
             return params[0] * -1;
         };

         protected void onPostExecute(Double result) {
             onCalculationCompleted(result);
         };
     }.execute(Math.random() * 100);
 }

 protected void onNetworkButtonClicked() {
     new AsyncTask() {
         @Override
         protected String doInBackground(String... params) {
             try {
                 Thread.sleep(5000); // A long network operation...
             } catch (InterruptedException e) {
                 // Nothing to do here...
             }
             final StringBuffer content = new StringBuffer(params[0]);
             return content.reverse().toString();
         }

         protected void onPostExecute(String result) {
             onRequestCompleted(result);
         };
     }.execute("www.google.com");
 }
}

Lets look at a few problems that arise with the AsyncTask usage:

  1. If an activity gets destroyed by a configuration change or if the user leaves the application while the doInBackground(…) is being executed, once the onPostExecute(…) method gets called you will improperly access UI elements and the application will probably crash;
  2. The nature of the AsyncTask class allows a usage model often called “fire and forget” as shown above where you call new AsyncTask<…>().execute(); This anonymous inner classes very often cause issues related to memory leaks, specially when a Context object is used within the class.

Lets sit back and think what developers actually need!? They need to be able to execute actions in the background and report these action’s results on the UI thread. How is it possible to support such model without the need to manage multi threading complexity???

Let me handle it for you 🙂 Look at the library project at https://github.com/dpsm/org.dpsmarques.android

So lets imagine an ideal scenario… The simplest you could get is to have a method to be overrriden where you could implement background operations and another where the results would be delivered into the UI thread for you 🙂

@Override
protected ViewUpdateData handleControllerAction(ControllerAction action) {
    ViewUpdateData result = null;
    switch (action.code) {
        case OP_COMPLEX_MATH_TEST:
            result = onComplexMathOperation((Double)action.param);
            break;
        case OP_NETWORK_TEST:
            result = onNetworkOperation((String)action.param);
            break;
    }
    return result;
 }

private ViewUpdateData onNetworkOperation(String url) {
    try {
        Thread.sleep(5000); // A long network operation...
    } catch (InterruptedException e) {
        // Nothing to do here...
    }
    final StringBuffer content = new StringBuffer(url);
    return ViewUpdateData.obtain(OP_NETWORK_TEST, content.reverse().toString());
 }

@Override
protected void handleViewUpdate(AsyncTestActivityView view, ViewUpdateData data) {
    switch (data.action) {
        case OP_COMPLEX_MATH_TEST:
            view.onMathOperationCompleted((Double) data.result);
            break;
        case OP_NETWORK_TEST:
            view.onNetworkOperationCompleted((String) data.result);
            break;
    }
}

The pattern above provides you two places to execute background and foreground operations:

  • protected ViewUpdateData handleControllerAction(ControllerAction action);
    Here’s the callback you always wanted! This method gets called on the background thread and you can do any heavy weight operation without any concerns;
  • protected void handleViewUpdate(AsyncTestActivityView view, ViewUpdateData data);
    The method above sounds cool, but how do I send UI updates once my background actions are completed? As shown in the code above, you need to create ViewUpdateData instance and return it. Once you return from the background method above, the object will get delivered to your handleViewUpdate(…) method as shown above.

For a full example look at the code example and the library code you need to use the pattern at https://github.com/dpsm/org.dpsmarques.android