最近搜狐面试的时候,被问到子线程中是否可以创建Handler当时比较蒙,没问答好,还有,View中的post和Handler中的post有啥区别,so现在来说说Android消息机制

Note:下面讨论的只是在UI线程中,或者传入的是主线程的Looper,UI线程也统一称为主线程

为什么要有消息机制

在Android中是不允许在主线程中更新UI的,so需要一个从子线程切换到主线的线程的机制,即耗时操作在子线程中执行,而当执行完毕后,需要将结果返给主线线程,主线程根据这些数据,更新相应的UI。

消息机制的几个对象

Message

Message包裹数据的携带对象

Handler

Handler主要负责把消息或者任务put到MessageQueue中,对消息的分发

MessageQuene

MessageQuene消息队列,一个单链表

Looper

Looper消息的发动机,不断地从MessageQueue中拿到消息,最后将消息给Handler分发。

Handler的机制

Handler的创建

对于Handler的创建,我们常常就是直接new Handler(),但是在Handler()的构造器还为我们初始化了所不知道的一些对象,new Handler()会调用Handler(Looper looper, boole aync)在这个构造函数中,会获取当前线程的Looper,而主线线程创建的时候会创建主线线程的Looper,将其保存在ThreadLocal对象中,所以在主线程直接new Handler()则得到的Looper就是主线线程的Looper,而当我们直接在子线程中new Handler(),在子线程中获取的Looper为null,就会抛出异常

Can’t create handler inside thread that has not called Looper.prepare()

如果非要在子线程创建Handler(),你需要传入一个Looper,这个Looper通常传主线程的Looper,这就能回答搜狐面试的问题了。

接下来从主线进程的Looper中获得MessageQuene。这个MessageQuene是从主线进程创建Looper的时候创建的

post(Running run),sendMessage(Message msg)

两个方法把msg的target也赋值上Handler.this后,这通过MessageQuene的enqueueMessage方法把Message压入到MessageQuene中。

dispatchMessage(Message msg)

每个消息都会有带有自己的target Handler来分发消息,最后调用handleMessage(Message msg),在默认的Handler中handleMessage是一个空方法,所以当我们要自己来处理消息的时候,需要重写这个方法也解释的通了。

Looper的机制

Looper的创建,主线的Looper创建在ActivityThread#main方法中创建的,在Looper的构造函数中创建了MessageQuene。ActivityThread#main在把一些准备工作做完后,开始消息循环Looper.loop();

创建的MessgeQuene中不断获得消息。而Message中有自己的目标Handler,也就是这个消息给谁来处理。最后调用dispatchMessage(Message msg),将消息分发掉。

当Handler发送的消息为空时,将退出整个消息循环,有时候发送null的消息会导致,这个线程的Looper消息循环退出,不建议发送空消息,只有在退出应用的时候可以发送空消息。

依赖图

依赖图

View中的post和Handler中的post有啥区别呢?

一个字😳,这是啥,一顿萌,原来在View中的post也是一个Handler的post,
这个Handler在ViewRootImpl中的ViewRootHandler,这个ViewRootHandler是在主线程中创建的,所以,View中的post和在Activity中Handler的post,只是两个不同的Handler,但是对应的是同一个Looper和MessageQueue