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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章