How to run background jobs using threads


SDK Version: 
M3

Previously I wrote about, that slow operations must be runned in threads. Now I would like to present some example code, how to use threads in Android.

Under the android system an user interface element can only be accessed from the thread that created it (the main UI thread). Thats where handlers and messages come in.

The user interface defines a handler like below:

  1. Handler handler = new Handler() {
  2.   @Override
  3.   public void handleMessage(Message msg) {
  4.     int arg1=msg.arg1;
  5.     int arg2=msg.arg2;
  6.     MyClass myObject=(MyClass)msg.obj;
  7.     //do something in the user interface to display data from message
  8.   }
  9. }

Then the thread, which can not touch the user interface, sends a message to this handler instead.

The following example code, that implements file downloading from net, represents how I usually use the threads:

  1. public class Downloader {
  2.   Thread thread=null;
  3.   boolean interrupted=false;
  4.   public File download(String UrlToDownloadFrom, File FileToSaveTo) throws Exception{
  5. //see more at helloandroid.com/tutorials/how-download-fileimage-url-your-device
  6.     ...
  7.     while (((current = bis.read()) != -1) && !interrupted) {
  8.       baf.append((byte) current);
  9.     }
  10.     ...
  11.     if(interrupted){
  12.       fileToSaveTo.delete();
  13.       return null;
  14.     }else
  15.       return fileToSaveTo;
  16.   }
  17.  
  18.   public void downloadInBackground(final String UrlToDownloadFrom, final File fileToSaveTo,final Handler handler){
  19.     thread = new Thread() {
  20.       public void run() {
  21.         Message message = new Message();
  22.         try{
  23.           message.obj=download(UrlToDownloadFrom,fileToSaveTo);
  24.           message.arg1 = 0;
  25.         } catch (Exception e) {
  26.           message.arg1 = convertExceptionToErrorcode(e);
  27.         }
  28.         if(!Thread.interrupted() && handler!=null){
  29.           //notify the user interface that the download is ready
  30.           handler.sendMessage(message);
  31.         }
  32.                                
  33.       }
  34.     };
  35.     thread.start();
  36.   }
  37.   public void interrupt(){
  38.     interrupted=true;
  39.     if(thread!=null && thread.isAlive())
  40.       thread.interrupt();
  41.   }
  42. }

This class offers functionality to run the downloading with and without a thread, th possibility to interrupt if started in a thread.

There is a built in class for this called AsyncTask but it is less flexible to use. For example you can not set the priority for AsyncTask jobs, and it bounds the background operation and the user interface operation together. But sometimes it is easier to use and a bit more efficient, maybe we will see AsyncTask in detail in a future article.