Handler机制 第一视角

2019-06-04  本文已影响0人  B_Crt

如题,本文以第一视角带你领略Handler真正的风采
本人看大到机制这一主题的时候,通常会看猪脚的定义(简单翻译):

发送处理和一个Thread相关联的Message或者Runnable。每个Handler和一个Thread以及那个Thread中的MessageQueue相关联。每当你创建一个新的Handler的时候,他就被绑定在创建Handler的线程和对应的MessageQueue上。从那时候起,Handler发送的Runnable或者Message都被发送到那个对应的MessageQueue上。而当Message或者Runnable从MessageQueue上取出来的时候就执行他。

上面一段描述可以很明显的抽出几个重点

  1. Handler发送和接收的是Message或者Runnable
  2. 每个Handler实例关联到一个Thread和Thread对应的MessageQueue
  3. 当MessageQueue从队列中取出时,Handle会执行他

Handler发送和接收的是Message或者Runnable

Handler提供出来发送的方法如下

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        // 封装成msg,发送到queue
        return enqueueMessage(queue, msg, uptimeMillis);
    }

每个Handler实例关联到一个Thread和Thread对应的MessageQueue

换句话,就是你通过一个Handler实例发送一个Message,他会找到对应的Thread中的MessageQueue并将Message插入。
关键来了,如果是你,你会怎么实现这么一个课题呢?
android系统的设计是:
设计一个Looper,每个线程都有自己的Looper。Looper管理MessageQueue。当Handler实例化的时候会有一个变量记录所在线程的looper。拿到looper就能拿到MessageQueue,接着就可以将Message插入MessageQueue。

当MessageQueue从队列中取出时,Handle会执行他

其实这句话包括2个课题,一个是取出(Looperd的loop方法会不断取出Message),一个是Handler的执行,这里我们先说Handler的执行。
如果是你,你如何让Handler在Message取出后,执行这个Message呢?换句话,如何找到这个Message对应的Handler并通知他?
android系统的设计是:
Message中添加了个字段:target 绑定对应的handler实例(插入MessageQueue的时候会进行判空,target为null抛出llegalArgumentException)。

最后,说一个大家很容易忽视的点。

public Handler(Callback callback, boolean async) {
    
        mLooper = Looper.myLooper();

    }

上面说到,Handler初始化的时候,通过持有引用mLooper的方式获取当前线程的Looper。那你有没有注意Looper的myLooper方法?

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

这个sThreadLocal就是ThreadLocal的应用,使每个线程都有这个变量的副本。

Handler初始化的时候通过持有引用的方式关联了Looper和对应的MessageQueue。并且Handler也记录了传进来的Callback。Handler发送Message到MessageQueue。Looper轮询MessageQueue取出Message,调用Message.target.dispatchMessage方法最终调用到Handler记录的Callback或者Message.callback。

上一篇下一篇

猜你喜欢

热点阅读