In my first ever article I am going to try to simplify the Handler, Looper and Handler thread class and the relation between them. Till now I have been struggling to understand the relation between them. So I thought of simplifying this for other people like me.
Let’s get started.
First of all lets see what is Handler Thread: Handler thread is nothing but a simple thread(as in Java) which execute certain task. It eventually extends the Thread class and also implement the run method of it. And to start it we can do Thread.start() method as with all others threads in Java.
So what is the difference?
So Imagine that you run into a problem where you want your thread to be running and you being able to post/send task to it so that it executes them basically what I mean is you want to reuse your thread. The way to do this in Java is
- Keep a thread alive i.e. do not let it come out of run method.
- Maintain a queue and post your task in it.
- Process the queue in your run method ie execute task one by one or when it comes
- Finish/Terminate the thread once done
I guess you see the issue that you have to manage lots of things and if not lot then at-least you should be very careful with this approach. But the good thing about Handler thread is it you can avoid all these. It comes with a message queue associated which can be used to send any message/task to this thread once it’s started. So how does Handler Thread does it?
Android has 3 main components to handle these which is used by HandlerThread. Let’s see them once.
Looper: Looper is a worker that keep a thread alive, It loops over message queue and send the message to respective Handler.
Handler: This class is responsible for enqueuing any task to message queue and processing them. Each Handler can be associated with one single thread and that thread’s message queue.
Message Queue: This class holds the list of messages to be dispatched by the looper. You can just call Looper.myqueue() to get list of messages. We do not normally deal with it.
Of-course you can use above three components with normal thread class also. You can create your own thread and use all above mentioned components. The process to do this is mentioned below
- Create a Thread class
- Call Looper.prepare inside run method.
- instantiate your Handler class and implement handleMessage method.
- Call Looper.loop()
I can write the code to do this but since I do not want you to follow that approach I will skip that. As this is not very efficient way, so Android has made job simpler by introducing HandlerThread.
We can write our own class which extends HandlerThread.. Each HandlerThread class has a looper associated with. We can use this looper to create Handler and then we can start enqueuing/sending message to this thread.
Steps to do it.
- Create a class that extend HandlerThread
- Instantiate your handlerThread class
- call start method // your thread is running now
- Create/Instantiate your Handler by using looper from handler thread created above
public abstract class BaseHandlerThread extends HandlerThread
{
public BaseHandlerThread(String name)
{
super(name);
}
@Override
protected void onLooperPrepared()
{
initHandler();
}private void initHandler()
{
mHandler = new Handler(getLooper()) {
@Override
public void handleMessage(Message msg)
{
//
}
};
}}
We can simply create instance of BaseHandlerThread and then call start() method on it. Once start is called Looper gets prepared. After Looper is prepared we get a callback where we are initialising the Handler. A handler can only be initialised after looper os prepared. Now you can use this handler to enqueue message.
When you want to terminate this thread just call quitSafely() method on your handler thread instance or quit() for OS version older then JELLY_BEAN_MR2.
When you do not want to create separate class and still want to use HandlerThread you can follow below step. Note that When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it. So be very sure about how you are creating the Handler.
//Create Handler
mHandlerThread = new HandlerThread("name");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
Thats about it. Feel free to share your input and point to improve on.