Androids Handler.post, what happens exactly
Asked Answered
C

3

10

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

?

Clement answered 10/4, 2014 at 9:18 Comment(0)
V
5

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.

Volteface answered 10/4, 2014 at 9:49 Comment(0)
B
9

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.
Blowbyblow answered 10/4, 2014 at 10:45 Comment(0)
V
5

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.

Volteface answered 10/4, 2014 at 9:49 Comment(0)
B
1

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.

Bountiful answered 10/4, 2014 at 9:40 Comment(2)
I would also add, that one has to associate a Looper with such a thread, by calling Looper.prepare() before creating a Handler, and by calling Looper.loop() after the handler is initialized.Volteface
I often use Handlers but I've never had to use Loopers... When do you have to use Loopers? Edit: Forget it, I've just seen your answer. Nice one. Good explaination.Bountiful

© 2022 - 2024 — McMap. All rights reserved.