欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-08 11:57:35
...

一 .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才不管你是不是主线程,它只是让绑定它的线程具有循环监听消息队列的功能