一、消息机制
在应用启动时,会执行 main() 方法, main() 会创建一个 Looper 对象,然后开启一个死循环,目的是不断从 消息队列 MessageQueue 里面取出 Message 对象并处理。
在Android中使用消息机制,会优先想到的是Handler。Handler可以轻松的将一个任务切换到Handler所在的线程去执行。在多线程的应用场景中,可以将工作线程中需要更新UI的操作信息传递到主线程去执行,从而实现工作线程更新UI的操作,最终实现异步消息的处理。
二. Handler机制模型
消息机制主要包含Handler、Message、MessageQueue,Looper这四个类。
-
Handler:消息辅助类。主要功能将 Message 对象发送到 MessageQueue 中,同时将自己的引用赋值给 Message#target (Handler.sendMessage())。也可以实现 handleMessage() 方法处理回调。
-
Message:消息实体。需要传递的消息也可以传递数据。
-
MessageQueue:消息队列。**内部实现并不是队列,而是利用单链表去实现因为在插入和删除数据有优势。**用于存储Handler发给来的消息( Message )以及取出。 内部使用单链表实现
-
Looper:与线程绑定,不止局限于主线程,绑定的线程来处理 Message 。不断循环执行 Looper.loop() ,从 MessageQueue 中读取 Message ,按分发机制将消息分发出去给目标处理(将 Message 发到 Handler.dispatchMessage 方法去处理)。
三、Handler运行流程
工作流程: 异步通信准备==>消息入队==>消息循环==>消息处理
1.异步通信准备
假定在主线程创建Handler,则会直接在主线程中创建 Looper , MessageQueue 和 Handler 对象。Looper和MessageQueue对象均属于其 创建线程 (由主线程创建则属于主线程)。创建 Looper 时会自动创建 MessageQueue 对象,创建好 MessageQueue 对象后, Looper 自动进入循环。 Handler 自动绑定 Looper 以及 MessageQueue 。
Looper 对象的创建方法一般通过 Looper.prepareMainLooper() 和 Looper.prepare() 方法。
2.消息入队
工作线程通过 Handler 发送 Message 到 MessageQueue 中。消息内容一般是UI操作,通过 Handler.sendMessage(Message message) 或 Handler.post(Runable r) 发送。加入 MessageQueue 一般通过 MessageQueue.enqueueMessage(Message msg,long when) 操作。
3.消息循环
分为消息出队和消息分发两个步骤
-
消息出队: Looper 从 MessageQueue 中循环取出 Message
-
消息分发: Looper 将取出的 Message 分发给创建消息的 Handler
消息循环过程中, MessageQueue 为空,则线程堵塞
4.消息处理
Handler 接受发过来的 Message 并处理。
四、Handler源码解析
1. 创建循环器对象( Looper )和创建消息队列对象( MessageQueue )
创建Looper对象主要有两个方法: Looper.prepareMainLooper() 和 Looper.prepare()
创建MessageQueue对象方法:创建Looper对象时会自动创建MessageQueue
// 源码位置:../core/java/android/os/Looper.javafinal MessageQueue mQueue;
final Thread mThread;
//Looper对象创建时会自动创建一个MessageQueue对象。
private Looper(boolean quitAllowed) {mQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();}//为当前线程(子线程)创建一个Looper对象 需要在子线程中主动调用该方法
public static void prepare() {prepare(true);}private static void prepare(boolean quitAllowed) {//判断sThreadLocal是否为null,不为空则直接跑出异常 可以保证一个线程只可以调用一次prepare方法if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocal.set(new Looper(quitAllowed));}//为主线程创建一个Looper对象 该方法会在主线程创建时自动调用
public static void prepareMainLooper() {prepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}}
1. 创建Looper
对象时会自动创建MessageQueue
对象
2.主线程的Looper对象是自动生成的,而子线程需要调用Looper.prepare()
创建Looper
对象
创建主线程是调用了ActivityThread
的main()
方法。
然后按照流程调用了Looper.prepareMainLooper()
和Looper.loop()
。所以主线程不需要调用代码生成
Looper对象。
3.Handler的主要作用是( 在主线程更新UI ),所以Handler主要是在主线程创建的。
4.Looper与Thread是通过 ThreadLocal 关联的。由于 ThreadLocal 是与线程直接关联的,
参考 prepare() 。
5.子线程创建Handler对象:无法在子线程直接调用Handler无参构造方法Handler创建时需要绑定Looper对象 。需要使用 HandlerThread 。
//源码位置: ../core/java/android/app/ActivityThread.javapublic static void main(String[] args) {...Looper.prepareMainLooper();Looper.loop();...}
2.开启Looper即消息循环
创建了 Looper和MessageQueue