Android开发艺术探索笔记——消息机制

消息机制概述

Android的消息机制主要指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作过程。

系统不允许子线程访问UI的原因是Android的UI控件不是线程安全的,多线程中并发访问可能导致UI控件处于不可预期的状态。

Handler创建时会采用当前线程的Looper来构建内部的消息循环系统。

Android的消息机制分析

ThreadLocal的工作原理

ThreadLocal是一个县城内部的数据储存类,通过它可以在指定的线程中储存数据。某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,就考虑用ThreadLocal,比如Looper。另一个使用场景是复杂逻辑下的对象传递,比如监听器的传递。

不同的线程访问同一个ThreadLocal的值,得到的结果是该线程中设置的值。这是因为ThreadLocal内部会根据不同的线程查找对应的值,ThreadLocal的set方法如下

Android开发艺术探索笔记——消息机制

put方法:

Android开发艺术探索笔记——消息机制

从上图可知,ThreadLocal的值在table数组中的储存位置总是为ThreadLocal的reference字段所标识的对象的下一个位置。

消息队列的工作原理

消息队列主要包含两个操作:插入(enqueueMessage)和读取(next)。读取操作本身会伴随着删除操作。next方法是一个无限循环的方法,如果消息队列中没有消息,那么next方法会阻塞在这里。

Looper的工作原理

Android开发艺术探索笔记——消息机制

Looper会不停的从MessageQueue中查看是否有新消息,如果有就立刻处理,否则一直阻塞在那里。

Looper在构造方法中会创建MessageQueue。

Looper.prepare()为当前线程创建一个Looper,主线程通过prepareMainLoop方法创建Looper,本质也是通过prepare方法实现的。

Handler的工作原理

Handler的功能是发送信息和处理信息。

Handler发送信息的过程仅仅是想消息队列中插入了一条信息。

Handler处理信息如下图所示:

Android开发艺术探索笔记——消息机制

Handler还有一个特殊的构造方法是通过特定的Looper来构造Handler。(HandlerThread的Looper和Handler绑定时用到)

主线程的消息循环

在main方法中系统会通过Looper.prepareMainLooper()在创建主线程的Looper以及MessageQueue,并通过Looper.loop()来开启主线程的消息循环。主线程还需要一个Handler来和消息队列进行交互,它内部定义了一组小系列性,主要包含了四大组件的启动和停止等过程。

ActivityThread通过ApplicationThread和AMS进行进程间通信,AMS以进程间通信的方式完成ActivityThread请求后会回调ApplicationThread中的Binder方法,然后ApplicationThread会向H发送信息,H收到信息后会将Application中的逻辑切换到ActivityThread中去执行。