美文网首页
Handler机制 第一视角

Handler机制 第一视角

作者: B_Crt | 来源:发表于2019-06-04 20:17 被阅读0次

    如题,本文以第一视角带你领略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提供出来发送的方法如下

    • post
    • postDelayed
    • sendMessage
    • sendMessageDelayed
      上面两个发送Runnable,下面两个发送Message。但,其实,提供上面两个是指丰富支持Runnable。最终会被封装成Message,发送到MessageQueue。
    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。

    相关文章

      网友评论

          本文标题:Handler机制 第一视角

          本文链接:https://www.haomeiwen.com/subject/efjlxctx.html