安卓Handler源码分析| 青训营笔记

59 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第2天

1. Handler是什么?

我们可以把Handler放入一个线程中,去处理与线程关联的Message以及CallBack()。将Messge放入消息队列中,通过Looper去提取并处理消息。

2. 介绍一下使用方法。

这段源码是在Looper.java注释中找到的。官方已经给了我们一个使用案例。

1659936828880.png 接下来我会从run方法中依次去讲解里面的代码到底干了什么。

3.Looper.preare()

提取自Looper.java。 1659937044151.png 可以看出来prepare会从ThreadLocal中去拿Looper,如果拿不到的话会去创建一个Looper。如果已经有了一个Looper那么就会抛出异常,因为从抛出异常的信息中就可以看出来一个线程中只能有一个Looper。

4.new Handler()

提取自Handler.java。 0954145f85fd731d6d8869fbbc5b26c.png 通过构造函数去将我们创建的Handler与线程以及Looper绑定(因为一个Looper对应一个线程),同时可以看到还获得了Looper的消息队列的引用。

5. handleMessage(Message msg)

让Handler去处理对应的msg信息。

6. sendMessage

sendMessage
    sendMessageDelayed
        sendMessageAtTime
            enqueMessgae

通过不断去找sendMessage的底层,发现最终调用的是Handler所关联的Looper中的消息队列的入队方法enqueMessgae

637c2fddb44dd558088cf722041054a.png

7.queue.enqueMessgae

入队细节 2bcd606ea62c71a245a33a706fd97e0.png

8.Looper.loop()

for (;;) {
    //细节省略
    msg.target.dispatchMessage(msg);
    //细节省略
}

可以看出来loop()函数是不断循环的去调用msg.target的dispatchMessage函数。

9.msg.target

那么msg.target是什么呢

image.png

可以看出来target中绑定的是handler,那么何时绑定的呢?去看6中的消息队列的入队函数代码。

10.官方推荐的俩种创建Message方法。

方法1: 提取自Messgae.java 39eb2572c54f9962bbc44f31b4c4b6a.png 方法2: 提取自Handler.java 1659937994546.png 方法2其实底层调用的还是方法1,那么为什么要用这种方式去创建呢,其实从源码中可以看出来,obtain方法中是在从一个对象池中去提取一个Message,优化资源的利用率。

11.dispatchMessage

接下来再看看我们在8中loop()方法中还没有讲解的一个方法。

提取自Handler.java aab35bad76e01f7be39f01576fe0a93.png 可以看出来,dipatchMessage会先去处理回调。如果回调是true,那么就不去执行handleMessage。如果回调是false,那么还会去执行handleMessage。

总结图解

image.png