概览
Android线程间通信是消息驱动的,Looper负责轮询,Message为消息,MessageQueue为Message的集合,Handler负责串联线程。本文基于android api 29源码,主要讲解java层的Handler机制。
先来个一般性的例子:
fun testOriHandler() {
var handler1: Handler? = null
var handler2: Handler? = null
Log.d("Ktest", "${
Thread.currentThread().name}:main")
thread {
Looper.prepare()
// 暂不考虑内存泄漏
handler1 = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d("Ktest", "${
Thread.currentThread()}:handler1.handleMessage")
}
}
Looper.loop()
}
thread {
Looper.prepare()
handler2 = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d("Ktest", "${
Thread.currentThread()}:handler2.handleMessage")
}
}
Looper.loop()
}
thread {
Thread.sleep(1000)
handler2?.sendMessage(Message.obtain(handler2, Runnable {
Log.d("Ktest", "${
Thread.currentThread()}:msg2.callback")
}))
Thread.sleep(1000)
handler1?.sendMessage(Message.obtain())
}
}
运行结果:
其大概的运行流程如下:
工作线程通过绑定了Looper线程的handler,发送Message到消息队列,而Looper线程无限循环的从消息队列中取Message,并在Looper所在线程,执行handler的dispatchMessage方法,实现了异步线程通信。
正式代码分析前先看看简略类图:
关键代码分析
其实也就四句话:
- 初始化Looper:Looper.prepare()
- 初始化Handler:handler1 = object : Handler()
- 开始循环:Looper.loop()
- 消息发送:handler1?.sendMessage(Message.obtain())
初始化Looper
// Looper.java
// 充当ThreadLocalMap的key和获取线程Looper的工具类
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepare() {
prepare(true); }
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
// 这里保证了prepare两次会抛错,保证一个线程对应一个looper
throw new RuntimeException("Only one Looper may be created per thread");
}
// 设置线程的Looper
sThreadLocal.set(new Looper(quitAllowed));
}
初始化当前线程.threadLocals,最终会调用ThreadLocal.createMap,给当前线程初始化threadLocals变量:
// ThreadLocal.java
public T get() {
Thread t = Thread.currentThread();
// 获取当前线程的threadLocals
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
// 设置当前线程.threadLocals初始值
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
// threadLocals初始化
createMap(t, value);
return value;
}
void createMap(Thread t, T firstValue) {
// 设置线程threadLocals
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
设置当threadLocals的初始值:
// ThreadLocal.java#ThreadLocalMap
private Entry[] table;
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[