Android Concurrent Programming: HaMeR framework - Tuong-Nguyen/Android GitHub Wiki

What is HaMeR?

The HaMeR framework allows background threads to send messages or post runnables to UI thread and any other thread's MessageQueue via handlers.

HaMeR refers to Handler, Message and Runnable

Mechanism

HaMeR framework

  • Looper runs a message loop on a thread using the MessageQueue
  • MessageQueue holds a list of messages to be dispatched by the Looper
  • Handler allows the sending and processing of Message and Runnable to the MessageQueue.
  • Message contains a description and data that can be sent to a handler
  • Runnable represents a task to be executed.

Class Diagram

Class diagram

Notes:

  • UI thread has a looper by default.
  • If the thread does not have a looper, this handler won't be able to receive messages so an exception is thrown.

Handler Class

  • Handler is the Message producer
  • Sending Message or post Runnable (task message) objects to the MessageQueue that associated with a Thread
  • Receives the objects from the Looper and processes the messages.

Instantiating a Handler

// Handler uses current Thread's Looper
Handler handler = new Handler();
 
// Handler uses the Looper provides
Handler handler = new Handler(Looper);

Looper and MessageQueue

  • Looper is Message consumer
  • Looper keeps the thread alive while it waits to receive more tasks
  • A thread can have only one Looper and one MessageQueue
  • Looper's thread can associate with multiple Handler

Preparing a Thread

UI thread or main thread already has a Handler, a Looper and a MessageQueue by default. Other threads must be prepared, we can do this as follows:

// Preparing a Thread for HaMeR
class LooperThread extends Thread {
      public Handler mHandler;
      public void run() {
          // adding and preparing the Looper
          Looper.prepare();
          // the Handler instance will be associated with Thread’s Looper
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
          // Starting the message queue loop using the Looper
          Looper.loop();
      }
  }

or use HandlerThread class

// The HandlerThread class includes a working Looper
public class HamerThread extends HandlerThread {
    // you just need to add the Handler
    private Handler handler;
    public HamerThread(String name) {
        super(name);
    }
}

Handling Messages with Handler

The Message objects dispatched by Looper are processed by the handler with the method Handler.handleMessage

public class MessageHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                // handle 'Hello' msg
                case 0:{
                    String hello = (String) msg.obj;
                    System.out.println(hello);
                    break;
                }
            }
        }
    }

Conclusion

In Android, if we want to achieve concurrent behavior, we need:

  • A handler by extending Handler class and override handleMessage method
  • Create a client (can be a service) that has association with the handler so that we can produce a message by handler.sendMessage(Message)
  • An Activity that has association with the handler so that the handler can access the UI.

Ref:

http://pierrchen.blogspot.com/2015/08/android-concurrent-programming-looper.html

https://code.tutsplus.com/tutorials/concurrency-on-android-using-hamer-framework--cms-27129