美文网首页
Handler 源码解析

Handler 源码解析

作者: XX杰 | 来源:发表于2020-09-22 18:55 被阅读0次

关联类
Handler Message MessageQueue Looper
1、handler 的构造方法

Handler(Looper looper, Callback callback, boolean async)
looper  :必须的
callback  :  处理handlemsg的
async : ???  defalut = false

2、handler 构造方法中会获取 looper 和 looper.queue (messageQueue)

3、sendMessage 流程

1、所有的sendMessage 都是走的  sendMessageDelayed 方法  最后走到 sendMessageAtTime 方法

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        // 里面只有两行 代码, 主要是  enqueueMessage 方法
        return enqueueMessage(queue, msg, uptimeMillis);
    }

2、enqueueMessage 方法其实走的是 messageQueue中的方法 ,该方法是synchronized 同步锁

//  注意这里,msg.target = this  // 把msg和调用他的handler绑定了
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;   
        // 这个参数暂时不研究
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

3、在MessageQueue的enqueueMessage 方法里面 分析 可以知道
message 是链表形式, 按照时间进行排序的 根据时间 插入到对应的位置

Message prev;
for (;;) {
  prev = p;     // P 是当前message链的头
  p = p.next;
   if (p == null || when < p.when) {   // when 是新插入进来的message的时间
          break;
  }
  if (needWake && p.isAsynchronous()) {
      needWake = false;
    }
  }
msg.next = p;  // 按照时间大从小到大的顺序,把 新的msg插入到链表里面 
prev.next = msg;
// 下面就是   判断messagequeue是否在被阻塞或者等待, 使用nativeWake 唤醒

4、MessageQueue中removeMessages方法是单链表的删除操作

5、handler.postDelayed()方法 实际上是 sendmessage方法,其中传入的 runnable,作为了 message的callback方法—————— 所以 我们messge 的时候,不要new了。直接handler.obtainMessage()

public final boolean postDelayed(Runnable r, Object token, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r, token), delayMillis);
    }

private static Message getPostMessage(Runnable r, Object token) {
        Message m = Message.obtain();
        m.obj = token;
        m.callback = r;
        return m;
    }

6、真正的轮寻,查找message 没有在 messageQueue里面,也没有在 handler里面,更没有在 message里面
Looper.prepare() 只是在 sThreadLocal.set(new Looper(quitAllowed)); 在当前线程里面设置一个 looper
main线程会自动存在
looper.loop() 方法就牛了

 for (;;) {
            Message msg = queue.next(); // might block
            try {  // 主要执行次方法, 
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            msg.recycleUnchecked();
        }
// 在 messageQueue 中 通过循环判断  msg的when是不是 》=now
是就获得message

在sendMessage的时候 回调用 nativeWake()  唤醒轮训的操作

相关文章

网友评论

      本文标题:Handler 源码解析

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