Handler的一点理解

原理

参照终于明白了Handler的运行机制

个人的一点理解

  本质上,Handler的使用就是从一个MessageQueue中不断取出其所绑定的Message,随后调用其本身的handleMessage(...)方法,但是使用Handler有三个基本要点:
  1.每个线程线程只有一个Looper,而Looper其实就是引用了一个MessageQueue

    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和当前线程相关绑定起来
    }

  2.Looper.loop()包含了一个死循环for(;;),在该循环中不断对当前线程唯一的Looper所引用的MessageQueeue执行出栈或者出队列操作,并通过message.target驱使每一条信息所绑定的Handler对该条message进行处理。

public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            msg.target.dispatchMessage(msg);    //无论是调用post()还是setTarget(),最后都会调用这个
            msg.recycleUnchecked();
        }
    }

  3.使用Handler.setTarget()或者Handler.post(...)在本质上就是往本线程对应的Looper传入一个message,也就是进栈或进队列操作,但两种方法有一个细微区别,setTarget()的结果是使得message.callback = null,而post(Runnable r)则是使得message.callback = r。这个细微区别就导致了是该条message的处理时机。实际上参照第2点代码可以知道,方法loop()中每次出栈或出队列都会调用msg.target.dispatchMessage(msg);,那么接下来阅读以下代码:

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

  明显可以看到方法内会根据message.callback是否为空选择不同的操作来执行,也就是说,如果Handler调用的不是setTarget(),而是post()的话,是不会执行Handler的handleMessage(msg)的,而是直接调用post(Runnable r)中的参数

  还有相当重要的一点是,主线程会自动调用Looper.prepareMainLooper();来完成Looper的初始化,而我们手动创建的线程是需要自己去手动调用Looper.prepare()完成初始化才可以获得一个指向MessageQueue的Looper。


  看完终于明白了Handler的运行机制的一点理解,随手写下来加强记忆,如果有错误,请指正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容