Crimes against code and using threads in Android

Tuesday, January 20, 2009

Labels:

In my career as a software engineer, I have encountered plenty of example code. As a Google Developer Advocate for Android, part of my job involves creating example code for illustrating certain concepts and APIs.
Most of the time, people will take a snippet of example code and bend it to their will until it no longer resembles the original. But that's the whole point: the sample code has served its purpose. It has illustrated some key concept and hopefully helped someone build some great software.

Last week I met with a developer who was working on a prototype application for a potential client of his. In the course of our discussion, he told me that he has been continuing to use some example code I provided him with, as-is, without modification. This of course made me very happy, but more importantly, made me think that perhaps this code might also be useful to other Android developers out there.

WARNING: This is about to get a bit technical, if you or your children grow faint at the sight of code, please stop reading now.

The tricky problem of multithreaded programming with a Graphical User Interface (GUI)

Every GUI widget framework I have ever encountered has been single-threaded (usually called "the main thread" or "the gui thread.") Learning how best to use other threads and have them "play nicely" with your widget framework of choice can be tricky. The main problem with most widget frameworks (including Android) is that you can't call methods on widget objects if your code is running in a non-GUI thread.

Horrible crimes against code that I have committed in the past

Way back in the 90's I was wrestling with the Swing UI framework. I was trying to write applications that used a "background" thread to do some long running thing. This included some horribly hacky things, like putting Thread.sleep() statements in my code at certain places until it kinda-sorta worked (the really frustrating thing about calling UI methods from non-GUI threads is that sometimes it does actually work!)

That was until I learned about

javax.swing.SwingUtilities.invokeLater(Runnable thingToDo) 
You can call the
invokeLater()
method from any non-GUI thread and it will invoke your
thingToDo.run()
method in the context of the UI thread, which means that your Runnable object can do things like update a progress bar etc.

In the Android framework, the
android.os.Handler
class does the same thing. The way you use it is slightly different, though. If you create an android.os.Handler object in the context of the GUI thread (in the onCreate() method of an activity, for example) then you can use that handler instance in the context of another thread in order to do your UI work.

My little code pattern

I decided to reuse a code pattern that I developed years ago for doing multithreaded GUI programming, and here it is:

public interface GUITask {
void executeNonGuiTask() throws Exception;
void after_execute();
void onFailure(Throwable t);
}

The basic idea behind this is that executeNonGuiTask() is invoked from a non-GUI thread. If it returns without throwing an exception, the after_execute() method will get called
from the GUI thread (this is important). If, on the other hand, executeNonGuiTask() throws an exception, that exception will be passed to the onFailure() method, again in the context
of the GUI thread.

Sometimes you need to do something that might take more than a handful of milliseconds (download a file, talk to a web service, compute the mahalanobis distance between data points etc.) If that something takes a human-noticable period of time, you'll want to do that activity on a non-GUI thread in order to keep the UI responsive. That something will either complete successfully, or it will fail for some reason (IOException on a network thread, trying to invert a singular matrix, etc.) If it completes, you will most likely want the end user to know about this, so you will probably want to do something with the UI. If it fails for some reason, you will also
probably want to affect the UI (even if it is to display a message to "try again later"), which is why after_execute() and onFailure() are always invoked in the context of the UI thread.

All you need is one thread

Another thing I have found in my own forays into multithreaded UI programs, is that you typically only need one non-UI thread to do your background processing. One technique which
has worked well for me is to have a "task queue" which is essentially just one thread that I can "feed" Runnable objects to. If I "feed" 3 Runnable objects to my task queue, that task queue
will execute the first, then the second and then the third Runnable object that has been "queued up".

Here's the code:


public class TaskQueue {
  private LinkedList<Runnabl> tasks;
  private Thread thread;
  private boolean running;
  private Runnable internalRunnable;
 
  private class InternalRunnable implements Runnable {
    public void run() {
      internalRun();
    }
  }
 
  public TaskQueue() {
    tasks = new LinkedList«Runnable»();
    internalRunnable = new InternalRunnable();
  }
 
  public void start() {
    if (!running) {
      thread = new Thread(internalRunnable);
      thread.setDaemon(true);
      running = true;
      thread.start();
    }
  }
 
  public void stop() {
    running = false;
  }

  public void addTask(Runnable task) {
    synchronized(tasks) {
        tasks.addFirst(task);
        tasks.notify(); // notify any waiting threads
    }
  }
 
  private Runnable getNextTask() {
    synchronized(tasks) {
      if (tasks.isEmpty()) {
        try {
          tasks.wait();
        } catch (InterruptedException e) {
          Log.e("androidx", "Task interrupted", e);
          stop();
        }
      }
      return tasks.removeLast();
    }
  }
 
 
  private void internalRun() {
    while(running) {
      Runnable task = getNextTask();
      try {
        task.run();
      } catch (Throwable t) {
        Log.e("androidx", "Task threw an exception", t);
      }
    }
  }
}


This code is entirely generic Java code except for the use of android.util.Log (which could easily be removed). To use it, just create a new TaskQueue, call the start() method,
then "feed" it Runnable objects by calling taskQueue.addTask(myTask); when finished, just call taskQueue.stop();

Back to my little pattern

The TaskQueue class above is really just meant to be a building block, a piece of code that can be used by other pieces of code. Here is the code that bridges the gap between the TaskQueue class above, the android UI framework and the GUITask interface I described earlier:


import android.os.Handler;
import android.os.Message;
import androidx.LogX;

public class GUITaskQueue {
private static final int HANDLE_EXCEPTION = 0x1337;
private static final int HANDLE_AFTER_EXECUTE = 0x1338;
private TaskQueue taskQ;
private Handler handler;
private static GUITaskQueue singleton;

public static GUITaskQueue getInstance() {
if (singleton == null) {
singleton = new GUITaskQueue();
singleton.start();
}
return singleton;
}

private GUITaskQueue() {
taskQ = new TaskQueue();
handler = new MyHandler();
}

public void start() {
taskQ.start();
}

public void stop() {
taskQ.stop();
}

public void addTask(GUITask task) {
taskQ.addTask(new GUITaskAdapter(task));
}

/**
* Adds a task with an associated progress indicator. The indicator's showProgressIndicator() gets
* called immediately then the hideProgressIndicator() gets called before the GUITask's
* handle_exception() or after_execute() method gets called.
*/
public void addTask(ProgressIndicator progressIndicator, GUITask task) {
if (progressIndicator == null) {
addTask(task);
} else {
addTask(new GUITaskWithProgress(task, progressIndicator));
}
}

private static class GUITaskWithProgress implements GUITask {
private GUITask delegate;
private ProgressIndicator progressIndicator;

GUITaskWithProgress(GUITask _delegate, ProgressIndicator _progressIndicator) {
delegate = _delegate;
progressIndicator = _progressIndicator;
progressIndicator.showProgressIndicator();
}

public void executeNonGuiTask() throws Exception {
delegate.executeNonGuiTask();
}

public void onFailure(Throwable t) {
progressIndicator.hideProgressIndicator();
delegate.onFailure(t);
}

public void after_execute() {
progressIndicator.hideProgressIndicator();
delegate.after_execute();
}
};

private static class GUITaskWithSomething {
GUITask guiTask;
T something;

GUITaskWithSomething(GUITask _guiTask, T _something) {
guiTask = _guiTask;
something = _something;
}
}

private void postMessage(int what, Object thingToPost) {
Message msg = new Message();
msg.obj = thingToPost;
msg.what = what;
handler.sendMessage(msg);
}

private void postException(GUITask task, Throwable t) {
postMessage(HANDLE_EXCEPTION, new GUITaskWithSomething(task, t));
}

private class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case HANDLE_EXCEPTION:
GUITaskWithSomething thingie = (GUITaskWithSomething) msg.obj;
thingie.guiTask.onFailure(thingie.something);
break;

case HANDLE_AFTER_EXECUTE:
GUITask task = (GUITask) msg.obj;
try {
task.after_execute();
} catch (Throwable t) {
LogX.e(t);
}
break;
}
super.handleMessage(msg);
}
}

private class GUITaskAdapter implements Runnable {
private GUITask task;

GUITaskAdapter(GUITask _task) {
task = _task;
}

public void run() {
try {
task.executeNonGuiTask();
postMessage(HANDLE_AFTER_EXECUTE, task);
} catch (Throwable t) {
postException(task, t);
}
}
}
}


To use the above code, just call GUITaskQueue.getInstance().addTask(myTask) where myTask is an object that implements GUITask.

Until next time...

I hope this has been helpful for those of you interested in multithreaded programming on Android. Feel free to use any of the above code in any project you like, but please keep in mind that Google and I cannot be held responsible if your giant killer robot malfunctions because of a bug in the example code (also, if you have a giant killer robot, can I take it out for a spin?) As always, drop us a comment below with your questions, comments or finished code to share with the world.

Mike Jennings
Android Developer Advocate

9 comments:

fred said...

Has anybody found a better method to debug multithreaded code than post-mortem analysis?

Dave Pelletier said...

Great sample, thanks Mike. I was able to use your code to easily create a file downloader class that implements GUITask. I could use some advice though. Right now, I can update my GUI in the constructor of my GUITask, and then again in the onFailure and after_execute functions. What I would like to do is update my GUI periodically while the executeNonGuiTask function is running. Basically I would like an on-screen indicator for the progress of the download. What would be the best way to go about this?

Thanks!

Anton Rymarchuk said...

Thanx.

2 Dave Pelletier, the calling of handler inside the nonGUITask may to help... I'm working with it now, please answer me if you found nice solution.

Divided Mind said...

Thanks for that! I've been struggling with multi-threading in android for an hour now.

BTW, the task force thing is in the standard Java library -- look up the Executor class in the docs.

Y.Ramesh Rao said...

Can i use this code sample for Handling something like network calls in order to get notification after the getting of the data response from the server.

Felipe Martinez said...

Hello Mr Jennings, I was looking at your post and trying to implement the task queue for an Android app I'm working on now, when I ended up in a google project called Android-eXtended or androidx. I've tried to find some documentation about it but there is no wiki and no other website apart from the google code site (I believe).

Is that project still running? is it finished? Is it possible to find documentation about it? Do you know about any other project similar to it?

Thanks for sharing your knowledge!

Kai said...

Nice article.

One question. Could I just use ThreadPoolExecutor to replace TaskQueue? It looks like ThreadPoolExecutor can do anything TaskQueue is doing.

Daniel said...

The pattern itself is excellent, but you might not need to implement it yourself (even based on this sample code). As of Android version 1.5, which virtually all consumer devices currently run at a minimum, the Android SDK contains an implementation of something close to this called android.os.AsyncTask. The only major difference is that AsyncTask doesn't guarantee that your tasks try to share a single worker thread. If you aren't concerned about the performance overhead of creating a thread per task rather than using a shared worker thread, you should probably consider using the "official" implementation.

Android app development said...

This is one of the efficient post.I like your blog style.This is one of the brilliant post.Good.Android app developers