转载一篇Handler机制文章以加深理解
http://blog.csdn.net/sinat_23092639/article/details/52334398
核心内容提要:
1、Handler就是一个和创建当前Handler对象的线程和线程的消息队列绑定的组件。
2、Looper是针对某个线程开启消息循环,线程是默认没有消息循环的,要调用prepare来为当前线程设置一个Looper,调用loop开启消息循环直到循环结束为止。
3、核心代码分析
public Handler(Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
(1)Handler不能没有Looper,否则报异常。
(2)Looper对象持有MessageQueue引用。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
(1)一个线程只能拥有设置一个Looper对象
(2)将Looper对象设置到ThreadLocal内
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
(1)获取ThreadLocal内的Looper对象
4、消息发送机制
sendMessage
sendMessageDelay
sendMessageAtTime
enqueueMessage 【最终调用】
5、获取消息
loop循环提取MessageQueue队列内的消息
6、总结:
一个线程对应一个Handler,因为Handler的构造函数内获取的是绑定了该线程的Looper;
一个线程只能一个Looper对象,从而只有一个MessageQueue(在Looper的构造方法初始化);
所有的线程共享同一个ThreadLocal对象,不同线程向ThreadLocal对象设置的Looper不同;
这里的关键还是ThreadLocal类,它可以在Handler对象需要与Looper对像关联的时候提供当前;
线程的关联的Looper,并从该Looper得到当前线程的消息队列引用,从而使得Handler对象在发送消息的时候可以发送到创建自己的线程的消息队列。而
此时该线程的Looper消息循环执行Message的时候已经在创建Handler的线程中;
使用静态的Handler对象避免出现内存泄漏。
网友评论