Android的Handler机制原理
创建流程:
主线程创建一个looper(只能有一个Looper),创建looper的同时,会在looper的内部创建一个消息队列(MessageQueue)
创建Handler的时候,我们会取出当前线程的Looper,不断的去轮询MessageQueue中的Message。
整体流程:
Handler在子线程中发送的消息,实际上就是在MessageQueue中添加一条Message,通过Looper中的消息循环取得Message交给Handler处理。
源码分析:
ThreadLocal概念:线程局部变量,是一种多线程间并发访问变量的解决方案。与其synchronized等加锁的方式不同,ThreadLocal完全不提供锁,而使用以空间换时间的手段,为每个线程提供变量的独立副本,以保障线程安全。
从性能上说,ThreadLocal不具有绝对的优势,在并发不是很高的时候,加锁的性能会更好,但作为一套与锁完全无关的线程安全解决方案,在高并发量或者竞争激烈的场景,使用ThreadLocal可以在一定程度上减少锁竞争。
通过ThreadLocal来创建线程的内部变量。只创建一个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) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
Looper的构造方法,在创建Looper的时候,MessageQueue对象也被创建好了,这样就能保证Looper中持有一个MessageQueue
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
MessageQueue的数据结构其实并不是队列,这里采用了单链表的形式,因为单链表在插入和删除时,比队列有优势。
Handler创建的时候,会调用Looper.myLooper这个方法来得到Looper
mLooper = Looper.myLooper();
Looper.myLooper这个方法其实就是从ThreadLocal中得到Looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Handler处理消息
/**
* 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);
}
}
默认情况下,Android中新开启的线程,是没有开启消息循环的,如果要在线程中使用Handler,那么就要先调用Looper.prepare,主线程中,自动创建了Looper对象
Handler是Looper的一个接口,用来想Looper的MessageQueue中发送Message
在非UI线程中,直接new Handler()是不可以的,因为Handler需要发送消息到MessageQueue,而你所在的线程中没有MessageQueue,所以必须要先创建Looper对象。
Android中为什么主线程不会因为Looper.loop()里的死循环卡死?
https://www.zhihu.com/question/34652589