An AsyncTask provides a few handy functions that allow it to update the UI whenever it’s done doing work. OnProgreesUpdate, OnPreExecute, and OnPostExecute allow the AsyncTask to update the UI with whatever information it needs. These methods work great when developing an Android client, but what about a Library?
That’s where I hit a problem. When building an Android library, asynchronous methods will need to be used, and the UI will certainly need to be updated. But by using an AsyncTask, the functions to update the UI need to be defined within an AsyncTask. This is bad. This means that any AsyncTasks used within an Android Library would be updating the UI, which should really be left to the Client Developer.
Now What?
So in developing an Android library, I’m looking for AsyncTask that allows updating of the UI to be done by a different developer, not the library Developer. I can think of two different methods to do this:
- Create Listener Interface for the AsyncTask, and a callback handler that allows the user of the library to “listen” for updates from the AsyncTask.
- Create a new version of the AsyncTask with its own listener and handlers.
Here's a rundown of what method two needs.
Creating a Listener
The listener is what the client creates to listen to updates from your new asynchronous method. Under the hood, the listener is a simple interface that defines several methods the client should implement.1: public interface Listener {
2: public void onUpdate(parameters....); //What the client should do went an
//update is recieved from the new
//async task
3: }
Creating a Callbackhelper
The callbackhelper has a handler that points to the UI thread. It is used by the new asynchronous method to update the UI thread from a different thread. The method that kicks off the asynchronous method must have access to this handler. For this example, I created a private class that has a listener and a handler. This class also has methods that allow it to update the UI.1: private class callBackHelper() {
2: Handler UIhandler;
3: Listener UIlisener;
4:
5: callBackHelper(Handler handler, Listener listener) {
6: UIHandler = handler;
7: UIlistener = listener;
8: }
9:
10: //Tell the UI that it needs to update
11: void doUpdate(parameters...) {
12: Handler.post(new Runnablenew Runnable() {
13: @Override
14: public void run() {
15: listener.onUpdate(parameters ...);
16: }
17: });
18: }
19: }
Creating the New Asynchronous Method
This can now be any type of thread you can think of. For this example, I just used a Java Thread. This method is within the library, and the client can call it.1: public void doAsyncTask(parameters ..., Listener listener) {
2: final callBackHelper callbackhelper =
new callBackHelper(new Handler(), listener);
3:
4: //implement a Thread here and pass the callbackhelper along.
//Call DoUpdate whenever
//the UI needs to be updated
6: }
That’s it! The client must create a listener and send it in as a parameter to the asynchronous method. This allows the asynchronous method to update the UI thread from a different thread with ease. This works great from a library perspective. The library writer can tell the UI it needs updating, while the UI writer can determine what to do when it needs to update.
1 Why go to the trouble of creating your own AsyncTask like class? Why not just send the listener into the constructor of a real AsyncTask and call listener.onUpdate from AsyncTask.onPostExecute?
That way puts a bit more of a limit on what you can actually do in the background. This is because the AsyncTask is tied closely to an Activity.
So by using the AsyncTask, the life of your background tasks may end because the Activity has been destroyed.
Also, your limited to just one background thread, as Android doesn't allow the creation of an AsyncTask within an AsyncTask.