首先,您需要了解
Message班级是什么样的。一个
Message对象除其他字段外还包含以下内容:
Handler target; // a handler that enqueued the message long when; // the time at which the message is to be processed [RUNNABLE] Runnable callback; = [SWITCHED] int what, int arg1, int arg2, Bundle data... bool isAsynchronous; // I will talk about it in the end
我用 [RUNNABLE] 和 [SWITCHED] 标记的
代表两种处理a的非重叠方式
Message。如果
callback不为null,则将忽略所有 [SWITCHED]
字段。如果
callback为空比
Message由下式定义 [SWITCHED]
字段和在任一处理
Handler's被覆盖的
handleMessage()或
handleMessage()所述的
Handler.Callback处理程序与被初始化。
该
MessageQueue由分类
when字段。该
Looper不会出列并处理消息,直到当前时间,如由测量的
SystemClock.uptimeMillis,大于或等于存储在消息的时间
when字段。
当您致电时
Handler#post(Runnable r),会发生以下情况:
Message
从池中获得A (类中的简单静态链接列表Message
)您
Runnable
已分配到消息的callback
字段。when
如果没有延迟或未经过特定时间,则将字段简单地设置为当前时间将
Message
排队到MessageQueue
。如果when
早于队列头的时间,它将成为新的头。如果不是,则将其插入中间,以便MessageQueue
按when
在
Looper
这是一个非终止循环从队列中出队中的消息并处理它们在序列(无交织),最终,我们出队的消息,并呼吁dispatchMessage()
在处理程序,最初发布的Runnable
。处理程序确定消息是 [RUNNABLE] 还是 [SWITCHED], 并进行相应处理。特别
run()
是callback
如果存在
这应该回答您有关
Runnable阻塞任务期间在UI线程上发布行为的问题-好的, 不,它不会中断正在进行的任务,也不会交织
。线程上发生的所有事情首先进入
MessageQueue,按钮单击或
Runnables从其他线程发布的自定义。基本上没有任何其他方式可以发生这种情况:
Looper.loop()只是使线程忙于其
for(;;)循环。
虽然有一些方法可以更改消息的顺序。
例如,在Looper /
Handler框架中有一个有趣的同步屏障概念。按照惯例,同步屏障只是一个
Message带有null的
target(因此,它基本上只是一个类似于标志的东西,没有处理程序可以分派它)。如果将其放入队列中
postSyncBarrier(),则出队的整个过程都会更改,直到使用将该同步屏障从队列中移除为止
removeSyncBarrier()。在
Messages没有被标记为
isAsynchronous将在所有被忽略,不会出队并进行处理。而是将扫描队列,直到
isAsynchronous= true找到带有的消息。然后将根据
when其时间安排并在时间到来时对其进行处理。
另外,您可以
Handler#postAtFrontOfQueue()根据文档中的说明调用不言自明的
此方法仅在非常特殊的情况下使用-它很容易使消息队列饿死,导致订购问题或产生其他意外的副作用。
我建议您浏览提到的所有类的源代码。它读起来就像一本好小说。



