Handler
MessageQueue
Looper
Handler
发送消息和处理消息
- sendMessage(Message msg)
- sengMessageDelayed(Message msg,long delayMills)
- dispatchMessage(Message msg)
1、msg.callback不为空则执行并结束,为空则进行下一步
2、mCallback执行返回true则结束,false继续下一步
3、handler的handleMessage方法执行
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
MessageQueue
链表,主要包含两个方法,插入和读取。对应的方法分别为enqueueMessage和next,enqueueMessage插入一条消息,next读取并移除一条消息。
- enqueueMessage:
遍历消息列表,插入到位置msg.when > pre.when && msg.when < next.when。详情查看enqueueMessage源码。- next:
无限的循环,从消息列表取出消息,如果没有消息就会阻塞在这里。
Looper
轮询消息
- prepare
- loop
一个死循环,唯一跳出循环的方式是MessageQueue的next方法返回了null。- quit
当Looper的quit方法被调用时,Looper会调用MessageQueue的quit或者quitSafely方法,通知消息列表退出。否则loop方法会无限循环下去。MessageQueue的next方法是一个阻塞方法,当没有消息时next方法会一直阻塞在那里,这也导致loop方法一直被阻塞在那里。如果MessageQueue的next方法返回Message,则loop会处理这条消息,msg.target.dispatchMessage(msg)。msg.target是发送消息的Handler,最终代码的执行是在创建Handler所使用的Looper中调用的,这样就成功的将代码逻辑切换到指定线程中执行了。
使用ThreadLocal来管理Looper,可以使每个线程有自己的一个Looper。
ThreadLocal:
- 当一个变量以线程为作用域,并且不同线程具有不同的数据副本时
- 当一个变量以线程为生命周期,且是复杂逻辑下的对象传递,比如监听器,函数调用栈比较深
ThreadLocal是一个线程内部的数据存储类
- 通过它可以在指定的线程中存储数据.
- 只有在指定的线程才可以获取到相应线程存储的数据。
每个线程有一个ThreadLocalMap,里面存放着<ThreadLocal,Object>键值对,可以分析ThreadLocal的get方法
1、先拿到当前线程
2、拿到当前线程的ThreadLocalMap
3、从ThreadLocalMap中取出key为当前ThreadLocal的值
4、如果值为空则调用setInitialValue()方法获取默认值
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();
}
网友评论