Handler系列--Looper

2019-03-23  本文已影响0人  小斌_bingor

前言

本系列文章,将分享与Handler相关的知识,包括Handler的结构,运作流程,各个类的作用、之间的关系


内容提要

本篇文章将分析Looper的作用,以及主要的方法


重要属性

    //线程局部变量,让每个线程存放自己的Looper
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    //主线程的Looper
    private static Looper sMainLooper;  
    //消息队列
    final MessageQueue mQueue;  
    //Looper对应的线程
    final Thread mThread;

重要方法

private Looper(boolean quitAllowed)

Looper的构造方法

        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();


prepare系列方法
public static void prepare()

在当前线程创建一个Looper,如果需要为Handler自定义一个Looper,就需要调用这个。需要注意,在调用loop()方法之前,必须先调用prepare(),而当需要队列结束,则调用quit()

private static void prepare(boolean quitAllowed)

实际执行创建的方法

    /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    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));
    }
public static void prepareMainLooper()

创建MainLooper,应用程序会在初始化的时候自动为我们创建MainLooper,所以我们自己永远不需要调用它,只需要在要用的时候getMainLooper()即可
可以看到,mainLooper的创建,其实也是调用了prepare()方法,并且设置为不可退出,只是由于是在主线程创建的looper,并且在主线程调用了loop(),所以所有持有mainLooper的Handler,都得以在主线程执行handleMessage()

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

    public static Looper myLooper() {
        return sThreadLocal.get();
    }

我们重新捋一下Looper线程切换的逻辑


public static void loop()

Looper的核心方法
其实很简单,一个死循环,将Message出列,当队列为空时,结束循环
msg.target指的是Message持有的Handler

    public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                return;
            }
            msg.target.dispatchMessage(msg);              
            msg.recycleUnchecked();
        }
    }


public void quit()

退出loop(),MessageQueue会把所有Message出列

    public void quit() {
        mQueue.quit(false);
    }


public void quitSafely()

退出loop(),一般来说,建议使用quitSafely(),MessageQueue会把所有未到期的Message出列,但是到期的会继续发送

    public void quitSafely() {
        mQueue.quit(true);
    }


public static Looper getMainLooper()

获取主线程Looper

    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

本篇内容到此结束,感谢收看~~

上一篇 下一篇

猜你喜欢

热点阅读