说到 Android 消息机制,就不得不谈到 Handler 机制,接下来本文以 android-29 的源码分析 Handler 机制的原理。
首先 Handler 是在 android.os 包下,与它在同一个包下的 Looper,Message,MessageQueue 等就是本文的重点。
// 举个例子
这是 handler 在子线程使用的典型实例,下面按步骤分析:
1. Looper.prepare()
static
调用后创建了 MessageQueue 和 Looper,并把 looper 的实例放入 ThreadLocal 中保存
2. 创建 handler
Handler提供了两种使用方式
第一种方式是直接实例化,调用handler的构造函数
//Handler.java#构造函数一
构造函数里有三个参数,分别是
looper:创建了 MessageQueue,在某个线程中遍历对应的消息队列,相当于发动机的角色。
callback:定义了 handleMessage() 方法,对接收到的消息进行处理,相当于快递分拣员的角色。
async:设置消息是否异步,默认是同步的,如果是异步将不受同步障碍的约束。
第二种方式是继承 handler,重写 handleMessage() 方法。
创建 handler 后,handler 就持有了 looper 和 messageQueue 的对象引用, 通过调用 sendMessage() 方法往 messageQueue 中发送消息,其实最终调用的是 MessageQueue的enqueueMessage() 方法
boolean
TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t))); 这行代码会不断地调用write()方法,直到管道中的数据全部读完
3.Looper.loop()
//Looper.java#裁剪代码
这里重点分析 Message msg = queue.next();
Message
mPtr的赋值是nativeInit(),网上暂时没找到Android Q的在线查看,暂时以Android P来分析native层的逻辑。 native层创建NativeMessageQueue对象后将对象id返回给java层,其中NativeMessageQueue创建时创建了Looper对象, 与java层Looper对象在创建时创建了MessageQueue对象恰恰相反
static
nativePollOnce()调用到native层,将mPtr根据id转为NativeMessageQueue对象
static
至此流程分析结束,下面附上总结图
Handler通过sendMessage()发送Message到MessageQueue队列;
Looper通过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理;
经过dispatchMessage()后,交回给Handler的handleMessage()来进行相应地处理。
将Message加入MessageQueue时,处往管道写入字符,可以会唤醒loop线程;如果MessageQueue中没有Message,并处于Idle状态,则会执行IdelHandler接口中的方法,往往用于做一些清理性地工作。
Tips:
1.为什么在主线程中使用handler不用调用Looper.prepareMainLooper()和Looper.loop()? 这是因为 ActivityThread 在初始化时已经调用过了,具体见如下源码。
//ActivityThread.java#
2.主线程中的Looper.loop()一直无限循环为什么不会造成ANR? 首先要明白ANR的定义,activity超时5s,service超时10s,broadcast超时20s,才会导致Application Not Response。
参考资料:
http://androidxref.com/http://gityuan.com/2015/12/26/handler-message-framework/http://gityuan.com/2015/12/27/handler-message-native/