Android消息机制-Handler原理(三)

一 .Handler的执行过程

  1.定义Handler对象,重写handleMessage方法

  2.handler 对象调用sendMessage 发送message,sendMessage 最终调用  sendMessageAtTime
  3.sendMessageAtTime方法又调用了 enqueueMessage 使message 加入到 消息队列 MessageQueue,并且执行了msg.target = this 把handler对象赋值给message对象的target属性
  4.线程中的Looper执行loop()方法,不断从消息队列当中读取消息。
  5.loop()取到消息后,执行 msg.target.dispatchMessage(msg) ,也就是执行Handler对象当中的dispatchMessage方法
  6.最终dispatchMessage 方法,可以执行第一步handler对象重写的handleMessage继而完成了整个消息传递

补充 7.如果,第二步中Handler 使用post方法发送一个runable对象而非send方法,runable传递给了message的callback,最终在dispatchMessage 中,判断callback!=null从而执行了runable对象

二 .相关类

A.Handler:作用是发送消息,执行消息

Handler的相关方法已经介绍过了,这里 ,最终发送消息都指向了sendMessageAtTime(除了sendMessageAtFrontOfQueue
//sendMessageAtTime源码
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }
最终执行消息都指向了dispatchMessage

B. Message:消息,target属性携带handler对象,callback属性可携带Runable对象

C.MessageQueue:消息队列,一个线程只有一个消息队列

类似现实中买票,每个人都是一个messge,如果不排队窗口售票员处理不过来,票也容易卖重复了。排成一队,一个一个处理。
sendMessageAtTime中调用了MessageQueue 的 enqueueMessage 方法使消息加入消息队列。
Looper调用MessageQueue的next方法从消息队列中取消息。

D.Looper:循环从MessageQueue里面取消息,并dispatch调度消息。每个线程一个Looper实例

1. Looper才是使消息队列循环起来的类,在UI主线程中, Actitivy创建的时候,已经执行了Looper.loop() 。在Activity源码中定义了变量ActivityThread 类型的变量  mMainThread,他就代表了主线程。ActivityThread 中定义了Looper,并最终执行了 Looper.loop()。所以在主线程中,可以直接发送消息,并且取消息。

2.但是在Thread中,并没有定义和调用Looper.loop(),这样你发消息取不出来,执行不了,所以,在子线程要想执行Handler 这一套机制,必须在Thread里调用Looper.loop()是消息循环起来

Handler机制的作用什么, 是让线程A发消息,告诉B线程执行消息。
这里既可以 子线程发送消息,让 主线程执行消息; 又可以主线程发消息让子线程执行消息。
Handler   发消息的线程 消息执行的线程 是两个概念。这里,子线程里给主线程send消息,会使消息在主线程执行。 主线程给子线程send消息,会使消息在子线程执行。
进一步,主线程在创建的时候,就已经执行了Looper.loop() 监听消息队列。 所以子线程发消息给主线程,可以随时就执行了
但是,主线程发消息给子线程,子线程默认又没有监听消息队列,发了消息没人收。所以才需要先执行  Looper.prepare()  使线程绑定Looper对象,然后执行Looper.loop() 使消息队列动起来,循环监听消息队列。

实际上,主线程发消息让子线程执行消息是不常见的,主要是为了解释清楚 Looper.prepare() 是和线程绑定,Looper.loop() 可以使线程循环监听消息队列。Looper才不管你是不是主线程,它只是让绑定它的线程具有循环监听消息队列的功能


猜你喜欢

转载自blog.csdn.net/kangyouv/article/details/73864985