First, you need to understand what the Message class is. The Message object contains, among other fields, the following:
Handler target;
What I noted with [RUNNABLE] and [SWITCHED] are two non-overlapping Message processing tools. If the callback value is not null, all [SWITCHED] fields are ignored. If the callback is null than Message , defined by the [SWITCHED] fields and processed either in Handler's overriden handleMessage() or in handleMessage() Handler.Callback , the handler was initialized with.
MessageQueue sorted by when field. Looper does not delete and process the message until the current time measured by SystemClock.uptimeMillis is greater than or equal to the time stored in the when message field.
When you call Handler#post(Runnable r) , the following happens:
A Message obtained from the pool (a simple static linked list in the Message class)
Your Runnable assigned to a callback message.
when field is simply set to the current time, if there is no delay or a certain time has passed
Message is placed in the MessageQueue . If when earlier than the head of the queue, he becomes a new head. If it is not, it is inserted in the middle so that the MessageQueue remains sorted when
Looper , which was in a loop without end, discarding messages from the queue and processing them sequentially (without weaving), finally cancels our message and calls dispatchMessage() on the handler that originally placed Runnable .
The handler decides whether the message is [RUNNABLE] or [SWITCHED] and processes it accordingly. In particular, it calls run() on a callback , if present
This should answer your questions about the behavior of your Runnable published in the user interface thread during the lock task - well, no, it does not interrupt the current task and does not bind . Everything that happens in the thread first gets into a MessageQueue , button click, or your custom Runnables that you send from other threads. Basically, there is no way this could happen in any other way: Looper.loop() just makes the thread busy with its for(;;) loop.
There are ways to reorder messages.
For example, there is an interesting sync cable concept in the Looper / Handler structure. The synchronization barrier is in agreement only with Message with a target value of zero (so this is basically just a flag thing, there is no handler to send it). If it is queued using postSyncBarrier() , the entire redefinition process changes until the sync cable is removed from the queue using removeSyncBarrier() . Messages , not marked as isAsynchronous , will be ignored, not deleted and processed at all. Instead, the queue will be checked until a message with isAsynchronous = true . Then it will be scheduled according to its when and processed when the time comes.
Alternatively, you can call the friendly Handler#postAtFrontOfQueue() , though, as stated in the documentation
This method is intended only for special cases - it can easily starve in a message queue, cause problems with ordering, or other unexpected side effects.
I suggest you look at the source code of all the mentioned classes. It reads like a good art book.