Skip to content

Android Kotlin – Handler and Runnable examples

  • by
Android Kotlin - Handler and Runnable example

1.Overview

In this article, we will learn about the Android Kotlin – Handler and Runnable along with examples.

2. Android Kotlin – Handler and Runnable

Normally, Android apps use the main thread to handle UI tasks and input events. This main thread collects these input events or messages in a queue (MessageQueue) and then processes them using an instance of the Looper class. By default, the main thread already has a Looper prepared.

This Looper keeps the main thread alive and manages the message queue. It takes each message from the queue and executes it on the thread.

A Handler gives you a mechanism to push tasks into this queue from any other threads thus allowing other threads to communicate with the UI thread. It doesn’t mean that the Handler supports only the main thread. It can push tasks to any thread’s queue that has a Looper.

You can use Handler to add a Runnable object or messages to the Looper to execute the code on the thread associated with the Looper.

Android associates each Handler instance with a single thread and that thread’s message queue. Whenever you create a new Handler instance, it is tied up to a single Looper. So, it will deliver all the messages and Runnable to that Looper’s message queue.

There are two primary uses for a Handler:

  1. Schedule messages and Runnable to be executed in the future
  2. Enqueue an action to be performed on a different thread than your own.

Few Handler constructors are deprecated which we have discussed separately in this article.

2.1. Schedule messages or Runnable

You can schedule messages by using the following methods:

  1. post 
  2. postAtTime(java.lang.Runnable,long)
  3. postDelayed
  4. sendEmptyMessage
  5. sendMessage
  6. sendMessageAtTime
  7. sendMessageDelayed 

The above post methods allow you to push Runnable objects to the message queue.

The sendMessage versions allow you to enqueue a Message object containing a bundle of data to be processed by the Handler’s handleMessage method. You had to create a subclass of the Handler class and implement the handleMessage method.

You can create your own threads, and communicate back with the main application thread through a Handler.

3. Handler Kotlin examples

3.1. Handler post method Kotlin examples

As discussed earlier, you can use the Handler to enqueue an action to be performed on a different thread. To specify the thread on which to run the action, construct the Handler using a Looper for the thread.

Once you’ve created a Handler, you can then use the post(Runnable) method to post the message to Looper’s message queue.

3.1.1. Run handler in main thread

Looper includes a helper function, getMainLooper(), which retrieves the Looper of the main thread. You can run code in the main thread by using this Looper to create a Handler.

val mainHandler = Handler(Looper.getMainLooper()).post {
            System.out.println("Thread : " + Thread.currentThread().name)
        }

3.1.2. Run handler in the current thread

To execute the handler in the current thread, then you have to retrieve the Looper of the current thread by using the Looper.myLooper method. All these use the local thread to execute the background task.

val mainHandler = Handler(Looper.myLooper()).post {
            System.out.println("Thread : " + Thread.currentThread().name)
        }

3.1.3. Specify the Looper of any thread

Alternatively, you can create a thread with Looper and use it to execute the background task.

val handlerThread = HandlerThread("HandlerThread");
handlerThread.start();

val backgroundHandler = Handler(handlerThread.looper).post {
    println("Thread : " + Thread.currentThread().name)
    handlerThread.quitSafely(); 
}

3.1.4. Update main thread from another thread

You can create another Handler to update the UI thread from your background thread:

val backgroundHandler = Handler(handlerThread.getLooper(), Handler.Callback() {

        
        Handler(Looper.getMainLooper()).post {
            System.out.println("Thread : " + Thread.currentThread().name)

        }
        
        return true
    }
})

3.2. Handler sendMessage Kotlin examples

You can use sendMessage to send a message object to Handler from any thread. The Handler receives the message object in the handleMessage callback method.

After receiving and looking at the message object, you can organize what is being sent to the thread associated with the Handler and push Runnable or message to the thread’s message queue accordingly.

For example, a thread sends bundle data to the Handler (incomingHandler). The incomingHandler receives the bundle data in the handleMessage callback and uses the data to update the main thread (the main thread is associated with the incomingHandler).

private val incomingHandler = IncomingHandler(this, Looper.getMainLooper())

Thread {
            try {
                val msg: Message = incomingHandler.obtainMessage()
                val bundle = Bundle()
                bundle.putString("MSG_KEY", "Executed in background thread")
                msg.data = bundle
                incomingHandler.sendMessage(msg)
            } catch (ex: Exception) {
                ex.printStackTrace()
                Toast.makeText(this, ex.message, Toast.LENGTH_LONG).show()
            }
        }.start()

    private class IncomingHandler(private val context: Context, looper: Looper)
        : Handler(looper) {

        override fun handleMessage(@NonNull msg: Message) {
            super.handleMessage(msg)
            val bundle = msg.data
            val displayMessage = bundle.getString("MSG_KEY")
            post { Toast.makeText(context, displayMessage, Toast.LENGTH_LONG).show() }
        }
    }

4. Conclusion

To sum up, we have seen the Android Kotlin – Handler and Runnable along with examples.

Leave a Reply

Your email address will not be published. Required fields are marked *