原理
Handler 通过post、send等发送消息时,会将消息插入到MessageQueue,Looper的loop方法循环从MessageQueue里读取消息,并交给Handler.dispatchMessage处理,由于Looper是以线程为作用域(以ThreadLocal保存),因此Looper调用Handler.dispatchMessage是切换到生成生成handler时的线程。
ThreadLocal
数据是以线程为作用域,不同线程具有不同的数据副本。可以在多个线程中互不干扰地存储和修改数据。
private ThreadLocal<Boolean> mThreadLocal = new ThreadLocal<Boolean>();
public void main(){
mThreadLocal.set(true);
new Thread(new Runnable() {
@Override
public void run() {
mThreadLocal.set(false);
mThreadLocal.get(); //子线程为false
}
}).start();
mThreadLocal.get(); //主线程仍为true
}
原理
- 在Thread类的内部有一个成员专门用于存储线程的ThreadLocal.ThreadLocalMap
此map以ThreadLocal 作为键,以具体数据做为value
ThreadLocal.ThreadLocalMap threadLocals = null;
- ThreadLocal get\set时先获取当前Thread的threadLocals,再从threadLocals这个Map中取当前ThreadLocal对象作为键对应的值。
public T get() {
Thread t = Thread.currentThread();
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;
}
}
return setInitialValue();
}
- 如果threadLocals为null,则调用setInitialValue方法初始化,以initialValue()返回值做为value
MessageQueue 消息队列
- 内部存储消息列表,以队列形式提供插入、删除操作
- 实现不是真正的队列,而是Message的单链表结构
主要方法
- enqueueMessage插入消息
- next,读取消息并删除,是一个无限循环的方法,如果消息队列中没有消息,那么next方法会一直阻塞在这里。当有新消息到来时,next方法会返回这条消息并将其从单链表中移除
Looper
不停从MessageQueue中查看是否有新消息,如果有新消息就会立刻处理,否则就一直阻塞在那里
主要方法
- Looper.preare()方法创建当前线程的Looper
- Looper.loop()来开启消息循环.loop是一个死循环,调用MessageQueue的next方法取出消息。唯一跳出循环的方式是MessageQueue的next方法返回了null。只有当MessageQueue被标记为退出状态时next才会返回null
- Loop.quit(),调用MessageQueue的quit或者quitSafely方法来通知消息队列退出
Handler
Handler 负责消息的发送和接收。
Handler的工作需要Looper,没有Looper的线程就会报错
消息发送
Handler发送消息的过程仅仅是向消息队列中插入了一条消息
post\send等系列方法
消息接收处理 dispatchMessage
- 如果消息本身有callback 直接调用handlerCallback方法处理,完成
- 如果Handler.mCallback非空,调用mCallback.handleMessage处理,返回true时完成
- 如果Handler.mCallback为空,或者非空但第2部返回false时,调用handleMessage处理。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}