Android AsyncTask return result

To get Android AsyncTask to return a result use a callback method (Observer pattern) by following these steps.

  1. Define a constructor for our async class which extends AsyncTask (we’re required to subclass/extend AsyncTask for use). Let’s call our AsyncTask class MyAsyncTask.
  2. Constructor parameter takes a class which will handle the AsyncTask result.  Usually an Activity or Fragment, but could be a Robolectric Unit Test class for example.
  3. Declare a member variable/private field to hold the handling Activity/Fragment/Test. We’ll call it ResultListener.  The constructor will assign its parameter input to this member variable.
  4. Declare an Interface within  MyAsyncTask. Let’s call it ResultListener
  5. ResultListener defines a single method that our handling class must implement.  Let’s name the method handleAsyncResult and in this case it’s going to take a single boolean as an input parameter.
  6. In onPostExecute, call our listener class handler method, supplying a value to the input parameter as appropriate for the outcome of doInBackground.

Here’s a concrete example of an Android AsyncTask returning a result:

 

public class MyAsyncTask<T> extends AsyncTask<T, Void, Boolean> {
    private final String TAG = this.getClass().getName();
    ResultListener listener;

    public interface ResultListener {
        void handleAsyncResult(boolean result);
    }

    WebProxy proxy;

    public MyAsyncTask(ResultListener listener) {
        this.listener = listener;
    }

    @Override
    protected Boolean doInBackground(T... params) {
        // do interesting long running things here, Network, database, etc.
        Log.i(TAG, String.format("doInBack: sending %s via Retrofit", params.getClass().getName()));
        return true;
    }

    @Override
    protected void onPostExecute(Boolean success) {
        listener.handleAsyncResult(success);
    }
}

As a bonus this AsyncTask uses a Type parameter <T> as input, so it can handle different input types for the AsyncTask.execute(input). This will make your AsyncTask more reusable and easy to extend for future use.

When MyAsyncTask completes doInBackground, it will pass a boolean to onPostExecute which we’re going to send along to our handling class through listener.handleAsyncResult(success).

Within our handling class (supplied to our AsyncTask constructor) we’ll need to do two things:

  1. Make our class implement our Interface by adding  “implements MyAsyncTask.ResultListener” after the class name.
  2. Define a method within our handling class with a signature that matches MyAsyncTask.ResultListener.

Here’s an example for our implementing class:

public class Test implements MyAsyncTask.ResultListener {
private boolean asyncResult;

@Override
public void handleAsyncResult(boolean result) {
    asyncResult = result;
}


@Test
public void firstAsyncTest() throws Exception {
    MyAsyncTask<Checkin> myTask = new MyAsyncTask<>(this);
    myTask.execute(someArrayOfTypeT);
    assertThat(asyncResult).isTrue();
}

}

Posted

in

,

by