Handler(四)--Looper

系列目录: Handler机制原理

1.prepareMainLooper()

    //Looper#prepareMainLooper
    public static void prepareMainLooper() {
        // 设置不允许退出的Looper
        prepare(false);
        synchronized (Looper.class) {
            //将当前的Looper保存为Looper。每个线程只允许执行一次
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

2.prepare()

    static final ThreadLocal sThreadLocal = new ThreadLocal();
    //Looper#prepare
    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));
    }

boolean quitAllowed表示Looper是否允许退出,true就表示允许退出,对于false则表示Looper不允许退出
sThreadLocal的作用已在之前文章中做过解析,异步ThreadLocal

3. Looper()

    //Looper#Looper
    private Looper(boolean quitAllowed) {
        // 创建MessageQueue对象
        mQueue = new MessageQueue(quitAllowed);
        // 记录当前线程
        mThread = Thread.currentThread();
    }

4. myLooper()

    //Looper#myLooper
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

sThreadLocal.get()是和prepare(boolean)方法里面的sThreadLocal.set(new Looper(quitAllowed))一一对应的。

5. loop()

    //Looper#loop
    public static void loop() {
         // 获取TLS存储的Looper对象
        final Looper me = myLooper();
        //没有Looper 对象,直接抛异常
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //获取当前Looper对应的消息队列
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        // 确保权限检查基于本地进程,而不是基于最初调用进程
        final long ident = Binder.clearCallingIdentity();
        // 进入 loop的主循环方法
       // 一个死循环,不停的处理消息队列中的消息,消息的获取是通过MessageQueue的next()方法实现
        for (;;) {
             // 可能会阻塞
            Message msg = queue.next(); // might block
             // 如果没有消息,则退出循环
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            // 默认为null,可通过setMessageLogging()方法来指定输出,用于debug功能
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
           // 用于分发消息,调用Message的target变量(也就是Handler了)的dispatchMessage方法来处理消息
            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            // 确保分发过程中identity不会损坏
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                // 打印identiy改变的log,在分发消息过程中是不希望身份被改变
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
            // 将Message放入消息池
            msg.recycleUnchecked();
        }
    }

loop进入循环模式,不断重复下面的操作

  • 读取MessageQueue的下一条Message
  • 把Message分发给相应的target
  • 再把分发后的Message回到消息池,以便重复利用

6. quit()

    //Looper#quit
    public void quit() {
        mQueue.quit(false);
    }

退出循环
将终止(loop()方法)而不处理消息队列中的任何更多消息

7. quitSafely()

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

处理完MessageQueue内当前的Messager列表后退出循环

你可能感兴趣的:(Handler(四)--Looper)