美文网首页
Handler原理

Handler原理

作者: 天天听听 | 来源:发表于2021-03-02 11:14 被阅读0次

    Handler原理注意是消息处理机制。

    1. Message:消息的bean类,主要包含what,data, callback等信息;
    2. Handler:消息的搬运工,主要是发送和处理;
    3. MessageQueue:消息队列,主要是效果的管理;
    4. Looper:在ThreadLocal里面,用来启动MessageQueue,会调用MessageQueue的next方法。主线程默认启动了
     for (;;) {
                Message msg = queue.next(); // might block
    

    消息队列启动。

    通过Looper.loop()启动,主线程默认启动了,其他线程需要自己启动,否则不能进行消息处理。
    ThreadLocal:构造方法是私有,通过获取当前的线程作为变量,保证每个线程的ThreadLocal只会是调用者的。

    消息分发

    如果是post还是postDelay,最终都会调用到:

    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
        }
    

    这是系统的开机时间,所以系统休眠了,会到延时处理失败。
    消息队列排序:在MessageQueue.enqueueMessage插入的时候排序

     if (p == null || when == 0 || when < p.when) {
                    // New head, wake up the event queue if blocked.
                    msg.next = p;
                    mMessages = msg;
                    needWake = mBlocked;
                } else {
                    // Inserted within the middle of the queue.  Usually we don't have to wake
                    // up the event queue unless there is a barrier at the head of the queue
                    // and the message is the earliest asynchronous message in the queue.
                    needWake = mBlocked && p.target == null && msg.isAsynchronous();
                    Message prev;
                    for (;;) {
                        prev = p;
                        p = p.next;
                        if (p == null || when < p.when) {
                            break;
                        }
                        if (needWake && p.isAsynchronous()) {
                            needWake = false;
                        }
                    }
                    msg.next = p; // invariant: p == prev.next
                    prev.next = msg;
                }
    

    根据代码如果我们要实现一个高优先级的消息,只需要把当前时间设置会0,就会插入到堆首,以保证可以快速响应。

    消息分发

    根据Looper.loop()方法,会不断调用next方法。

    // Return here if the message loop has already quit and been disposed.
            // This can happen if the application tries to restart a looper after quit
            // which is not supported.
            final long ptr = mPtr;
            if (ptr == 0) {
                return null;
            }
    
            int pendingIdleHandlerCount = -1; // -1 only during first iteration
            int nextPollTimeoutMillis = 0;
            for (;;) {
                if (nextPollTimeoutMillis != 0) {
                    Binder.flushPendingCommands();
                }
    
                nativePollOnce(ptr, nextPollTimeoutMillis);
    

    内部也是一个死循环,会不断暂停在nativePollOnce方法中,nextPollTimeoutMillis是暂停时间,其中的是遍历所有消息队列得到的值。-1表示永久阻塞,直至有新消息进来,唤醒。
    next方法会返回下一个需要处理的消息。

    if (msg != null) {
                        if (now < msg.when) {
                            // Next message is not ready.  Set a timeout to wake up when it is ready.
                            nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                        } else {
                            // Got a message.
                            mBlocked = false;
                            if (prevMsg != null) {
                                prevMsg.next = msg.next;
                            } else {
                                mMessages = msg.next;
                            }
                            msg.next = null;
                            if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                            msg.markInUse();
                            return msg;
                        }
                    } else {
                        // No more messages.
                        nextPollTimeoutMillis = -1;
                    }
    

    获取到待处理Message,Looper会调用dispatchMessage方法

      try {
                    msg.target.dispatchMessage(msg);
                    if (observer != null) {
                        observer.messageDispatched(token, msg);
                    }
                    dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
                } 
    

    target:Message的handler,最终调用:

     /**
         * Handle system messages here.
         */
        public void dispatchMessage(@NonNull Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }
    

    最后就会执行我们重写的handleMessage方法。

    相关文章

      网友评论

          本文标题:Handler原理

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