swirl logo

About     Archive     Feed     Impressum

Threading in Android

Foreword

Devs are busy most of the time and don't have time to read very long articles. This article is as short as possible and contains as much as possible information about threading in Android. Let's start!

Architecture

Multitasking and Multithreading

Processes

Android process architecture

Note: It is also possible but very rare that...

Application Lifecycle

Application start

General:

App startup sequence:

  1. Start Linux process
  2. Create runtime: Dalvik or ART (Android Runtime)
  3. Create Application instance (android.app.Application.onCreate() is called)
  4. Create the component for the application (e.g. Activity, Service, ...) - It is the component that needs to be executed and triggered the startup

Application end

Android kills the process when:

Important:
There's no guarantee that onDestroy() (Activity, Service) will be called

Memory-Management

General

Process Hierarchy

Process importance (from high to low):

Foreground Process:

Visible Process:

Service Process:

Background Process:

Empty Process:

Important:
Priorities are done at the process level and not the component level. A single component can push the entire process into the foreground level.

Thread Scheduling

A thread scheduler decides which threads in the Android system should run, when, and for how long

Android’s thread scheduler uses two main factors to determine the scheduling:

Niceness Values

Control Groups (Cgroups)

Main Thread aka UI Thread

General:

Responsiveness:
Always ensure that no long-running tasks are executed on the UI thread!
A long running task will block other sensitive tasks on the UI thread (e.g. animations)

Example: Let's consider a simple view animation:

The calculation is a bit simplified. However, be cautious about possible long running tasks.

Service

Use Service for very short tasks without UI; for longer tasks use threads within Service

General

Lifecycle

Start: A service starts...

End: A service ends...

Example

public class MyService extends Service {
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      return MY_START_MODE;
   }

   @Override
   public IBinder onBind(Intent intent) {
      return null;
   } 
}

IntentService

Use IntentService for repetitive and/or long tasks that should run on the background, independent of the UI

General:

Lifecycle

Start:

End:

Example

public class MyIntentService extends IntentService {
    public static final String MY_PARAM = "param";

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String msg = intent.getStringExtra(MY_PARAM);
        // do something
    }
}

AsyncTask

Use AsyncTask for short(!) (repetitive) tasks that are tightly bound to the UI

General

Lifecycle

Start:

End:

Example

public class MyActivity extends Activity {
    private TextView textViewStatus;
    public void onCreate(Bundle savedInstanceState) {
           // init...
           MyAsyncTask task = new MyAsyncTask();
           task.execute(urls); // e.g download urls
    }

    private static class MyAsyncTask extends AsyncTask<String, Void, String> {
            @Override
            protected String doInBackground(String... urls) {
                    // download something via url and return result
                    return downloadResultAsString; // e.g. "lorem ipsum"
            }

            @Override
            protected void onPostExecute(String result) {
                    textViewStatus.setText(result); // sets "lorem ipsum" to TextView textViewStatus
            }
    }
}

Message Passing

Scenario: "We are running on a client thread and want to have code executed in another thread context"

Message Passing Parts:

General:

Android threading handler relation

Process:

  1. The producer thread inserts a Message into the MessageQueue by using a Handler which is connected to the consumer Thread
  2. The Looper runs in the consumer Thread, retrieves the Message from the MessageQueue and "sends" the Message to the Handler which is still connected to the consumer Thread
  3. The Handler executes the Message via handleMessage(Message)

Android threading handler relation

More Details:

Thread:

MessageQueue:

Message:

Looper:

Handler:

Example

class MyLooperThread extends Thread {
    public Handler handler;

    public void run() {
        // Initialize a Looper and associate it with the current thread
        Looper.prepare();
        handler = new Handler() {
            @Override public void handleMessage(Message msg) {
                // handle incoming message
            }
        };
        // Starts the Looper
        Looper.loop();
    }
}
class MainActivity extends Activity {
    public void onCreate(...) {
        // Other stuff
        MyLooperThread myThread = new MyLooperThread();
        myThread.start();

        // much later, send a message
        Message msg = myThread.handler.obtainMessage(0);
        myThread.handler.sendMessage(msg);
    }
}

HandlerThread

Use HandlerThread to establish an ongoing, one-way inter-thread communication

General

Example

HandlerThread myThread = new HandlerThread("MyHandlerThread");
myThread.start();
Handler handler = new Handler(myThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        // TODO: process message
    }
};

Loaders

General

Development Phase & Debugging

Feedback? Questions? Errors? Let me know what you think.

Hire me!