Looper/Handler API - Part 4

06 Feb 2017

Contents

last modified: 06-feb-2017 (22:19)

This is part 4 of looper/handler API series

Background

This part belongs to Looper. A Looper fetches Message from the MessageQueue and dispatch it to handler and it happens only if current timestamp is greater than Message’s timestamp. If there is no message to dispatch or having timestamp less than current timestamp then Looper blocks the thread and wait for messages to reach their dispatch time.

We can also set listener for these time gaps between messages. i.e if MessageQueue detects time gaps between messages, it invokes MessageQueue.IdleHandler on Queue.

MessageQueue mq = Looper.myQueue();
MessageQueue.IdleHandler idleHandler = new MessageQueue.IdleHandler();
mq.addIdleHandler(idleHandler); //  add
mq.removeIdleHandler(idleHandler); // remove

Usage

A looper has 3 important methods to remember

Prepare

Looper.prepare() attaches a Looper to current thread and initializes it i.e. sets up MessageQueue.

A thread can have only one Looper attached to it. If a thread has already a Looper and you call Looper.prepare() on that thread, it will generate a runtime exception.

Loop

Looper.loop() is a blocking call, which prevents the current thread from termination. Anything after Loop.loop() method will not be executed unless you call Looper.quit().

Quit

Looper.quit() methods breaks the Loop and allows the read to complete its execution.

Here is a snipped from example in part 1.

    @Override
    public void run() {
        Looper.prepare();
        mHandler = new Handler(this);
        Looper.loop();

        if(LOG){
            log("run -> %s", "terminating worker thread.");
        }

    } // run

Main Looper

When application starts a Looper is attached to main thread (UI thread). You can get this Looper from anywhere in the application by calling Looper.getMainLooper(). Main Looper is a little different than looper we create manually.

java.lang.IllegalStateException: Main thread not allowed to quit