since several days, I tried to figure out what exactly happens if I execute code in
void function(){
//somePreExecutionCode
new Handler().post(new Runnable(){
@Override
public void run(){
//someCode
}
});
}
It seems like it isn't blocking the UI, so buttons, which calls function() doesn't stuck in the clicked position until someCode has finished.
But if somePreExecutionCode starts a progressBar, the progressBar is shown at exactly the same moment, when someCode has finished.
I know, there are AsyncTasks for, but is there any other possibility?
And whats the difference between
new Handler().post
and
View.post
?
Putting it simply, there are Looper threads, for example, UI thread. Such thread has its own Looper, which runs a message loop for the thread.
Such thread, typically, has a Handler, which processes its Looper
's messages - overriding public void handleMessage(Message msg)
or executing a Runnable
, which was posted to it's looper's message queue.
When you're creating a Handler
in the context of UI thread (like you did in your code), it gets associated with UI thread's looper, so your \\someCode
runs on UI thread.
I guess, in your use case new Handler().post(Runnable)
and View:post(Runnable)
are mostly the same, as they both add a Runnable
to the UI thread message queue.
But they are not the same.
View:post(Runnable)
will add a Runnable
to the UI thread looper's message queue;
Handler:post(Runnable)
will add a Runnable
to its associated thread looper's message queue
My explanation is pretty much intuitive, so correct me anyone if I am wrong.
When an Android application is created, system creates a main thread of execution. This thread is referred to as UI thread and all UI related operations happen on this thread in order to avoid synchronization issues.
A Looper instance is created on this thread, which has a MessageQueue data structure. The Looper will be in an infinite loop waiting to read the Message / Runnable instances posted on the MessageQueue. To add Message7 / Runnable to the MessageQueue, Handler is used.
When you create a Handler instance, it will be associated with the current thread of execution and the Looper instance created on that particular thread.
Hence when you post a message via a Handler, the Message is added to the MessageQueue, which will be read in FIFO order by Looper and will be delivered to the target.
new Handler().post() and View.post are bit different.
- When you post Messages via View.post, you are guaranteed the Message will be posted on UI thread's MessageQueue, since it internally uses Handler instance created on UI Thread.
- If you create Handler instance on UI thread and post the Message using it on any thread, Message will be posted to the UI thread's MessageQueue.
- If you create Handler instance on a non-UI thread and post Messages using it, they will be posted on non-UI thread's MessageQueue.
According to the Android View's documentation:
The Runnable will be run on the user interface thread
According to the Android Handler's documentation:
The Runnable will be run on the thread to which this handler is attached
So, in the Handler's case, you can create it in any thread you want, it's a kind of anchor that will execute the Runnable you provide in the thread it was created in.
In the View.post, you will always execute the Runnable in the uI thread.