欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android的Handler机制原理

程序员文章站 2022-05-14 17:57:43
...

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

相关标签: Handler