从开发的角度来说,Handler
是Android消息机制的上层接口,这使得在开发过程中只需要和Handler
交互即可。Handler
并不是专门用于更新UI的,只是常被开发者用来更新UI。
Android的消息机制主要是指Handler
的运行机制,Handler
的运行需要底层MessageQueue
和Looper
的支撑。我们经常提到的主线程,也叫UI线程,它就是ActivityThread
,ActivityThread
被创建时就会初始化Looper
,这也是在主线程中默认可以使用Handler
的原因。
1. Android的消息机制概述
Handler
的主要作用是将一个任务切换到某个指定的线程中去执行。系统之所以提供Handler
,主要原因就是为了解决在子线程中无法访问UI的矛盾。系统不允许在子线层中访问UI,是因为Android的UI控件不是线程安全的。
Handler
的工作原理:Handler
创建时会采用当前线程的Looper
来构建内部的消息循环系统,如果当前线程没有Looper
,那么就会报错。为当前线程创建Looper
即可。
(如图的工作过程可以理解为:Thread1为A线程,Thread2为B线程,A线程利用B线程创建的Handler
给B线程发送消息。)
2. Android的消息机制分析
Android的消息机制实际上就是Handler
的运行机制。
1. ThreadLocal
的工作原理
ThreadLocal
是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其他线程来说则无法获取到数据。ThreadLocal
的使用场景,一般来说,当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,就可以考虑采用ThreadLocal
;另一个使用场景是复杂逻辑下的对象传递。
在不同线程中访问同一个ThreadLocal
的set
和get
方法,它们对ThreadLocal
所做的读/写操作仅限于各自线程的内部,所以ThreadLocal
可以在多个线程中互不干扰地存储和修改数据。
2. 消息队列的工作原理
消息队列在Android中指的是MessageQueue
,MessageQueue
主要包含两个操作:插入和读取。读取操作本身会伴随着删除操作,插入和读取对应的方法分别为enqueueMessage
和next
,其中enqueueMessage
的作用是往消息队列中插入一条消息,而next
的作用是从消息队列中取出一条消息并将其从消息队列中移除。
3. Looper
的工作原理
Looper
在Android的消息机制中扮演着消息循环的角色,具体来说就是它会不停地从MessageQueue
中查看是否有新消息,如果有新消息就会立刻处理,否则就一直阻塞在那里。Handler
的工作需要Looper
,没有Looper
的线程就会报错。通过Looper.prepare()
即可为当前线程创建一个Looper
,接着通过Looper.loop()
来开启消息循环。
4. Handler
的工作原理
Handler
的工作主要包含消息的发送和接收过程。消息的发送可以通过post
的一系列方法以及send
的一系列方法来实现,post
的一系列方法最终是通过send
的一系列方法来实现的。Handler
发送消息的过程仅仅是向消息队列中插入了一条消息,MessageQueue
的next
方法就会返回这条消息给Looper
,Looper
收到消息后就开始处理了,最终消息由Looper
交由Handler
处理,即Handler
的dispatchMessage
方法会被调用,这时Handler
就进入了处理消息的阶段。dispatchMessage
的实现如下所示:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
3. 主线程的消息循环
Android的主线程就是ActivityThread
,主线程的入口方法为main
,在main
方法中系统会通过Looper.prepareMainLooper()
来创建主线程的Looper
以及MessageQueue
,并通过Looper.loop()
来开启主线程的消息循环。