美文网首页
Handler 消息机制详解

Handler 消息机制详解

作者: wildeyess | 来源:发表于2020-07-02 17:35 被阅读0次

    1. Handler,Looper,MessageQueue,Message他们的作用与关系

    1.1Handler

    Handler使您可以发送和处理[Message](https://developer.android.com/reference/android/os/Message)与线程的关联的Runnable对象[MessageQueue](https://developer.android.com/reference/android/os/MessageQueue)。每个Handler实例都与一个线程和该线程的消息队列关联。当您创建新的处理程序时,它会绑定到[Looper](https://developer.android.com/reference/android/os/Looper)。它将消息和可运行对象传递到该Looper的消息队列,并在该Looper的线程上执行它们。

    Handler有两个主要用途:(1)计划消息和可运行对象在将来的某个时刻执行;(2)使要在与您自己的线程不同的线程上执行的操作排队。
    以上是官方翻译说明,Handler在我们平常的使用主要是用于异步消息通知,在子线程中通知主线程做什么事,比ui刷新,或者延时执行某个操作。

    1.2Message

    定义一条消息,其中包含可以发送到的描述和任意数据对象[Handler](https://developer.android.com/reference/android/os/Handler)。该对象包含两个额外的int字段和一个额外的对象字段,在很多情况下,这些字段使您不必进行分配。

    message是消息通知机制的载体,Handler发送的信息都在放在Message中。

    1.3MessageQueue

    Low-level class holding the list of messages to be dispatched by a [Looper](https://developer.android.com/reference/android/os/Looper). Messages are not added directly to a MessageQueue, but rather through [Handler](https://developer.android.com/reference/android/os/Handler) objects associated with the Looper.
    You can retrieve the MessageQueue for the current thread with [Looper#myQueue()](https://developer.android.com/reference/android/os/Looper#myQueue()).

    消息队列,Handler发送的消息都在它这管理,提供加入消息,和获取消息的方法

    1.4Looper

    用于为线程运行消息循环的类。默认情况下,线程没有与之关联的消息循环;要创建一个,请[prepare()](https://developer.android.com/reference/android/os/Looper#prepare())在要运行循环的线程中调用 ,然后 [loop()](https://developer.android.com/reference/android/os/Looper#loop())让它处理消息,直到循环停止为止。
    与消息循环的大多数交互是通过 [Handler](https://developer.android.com/reference/android/os/Handler)类进行的。

    Looper可以理解为一个循环执行某个操作的类,这个类是和线程绑定的。它的循环操作就是不断的从MessageQueue中将可以发送的消息拿出来交给Handler处理

    1.5他们之间的关系

    1. Handler发送消息 消息到哪了 ?到messageQueue了 Handler(sendMessage)=====message====>MessageQueue
    2. Handler 处理消息 消息哪来的? Looper执行它的循环拾取操作 MessageQueue======Message======>Handler(dispatch)
    • Looper有一个MessageQueue消息队列;
    • MessageQueue有一组待处理的Message;
    • Message中有一个用于处理消息的Handler;
    • Handler中有Looper和MessageQueue。

    2.源码解析

    2.1 Handler源码分析

    Handler的创建,构造函数。这里讲解两个最重要的构造函数,其他的构造方法都是调用这两个,发送消息和处理消息的方法

      /**
         * 使用当前线程的Looper进行Handler的创建
         * Use the {@link Looper} for the current thread with the specified callback interface
         * and set whether the handler should be asynchronous.
         * <p>
         * Handlers are synchronous by default unless this constructor is used to make
         * one that is strictly asynchronous.
         * <p>
         * Asynchronous messages represent interrupts or events that do not require global ordering
         * with respect to synchronous messages.  Asynchronous messages are not subject to
         * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
         *
         * @param callback The callback interface in which to handle messages, or null.
         * @param async    If true, the handler calls {@link Message#setAsynchronous(boolean)} for
         *                 each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
         * @hide
         */
        public Handler(@Nullable Callback callback, boolean async) {
            //匿名类、内部类或本地类都必须申明为static,否则会警告可能出现内存泄露
            if (FIND_POTENTIAL_LEAKS) {
                final Class<? extends Handler> klass = getClass();
                if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                        (klass.getModifiers() & Modifier.STATIC) == 0) {
                    Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                            klass.getCanonicalName());
                }
            }
            //获取当前线程的looper对象,myLooper方法会在讲解Looper时进行说明
            mLooper = Looper.myLooper();
            if (mLooper == null) {//当我们在子线程中创建Handler,并使用该构造方法,就会报该错误,
                // 平时在主线程中创建Handler时,已经在创建Activity时生成了mainLooper,所以不需要创建
                throw new RuntimeException(
                        "Can't create handler inside thread " + Thread.currentThread()
                                + " that has not called Looper.prepare()");
            }
            //相关属性赋值,获取消息队列
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    
        /**
         * 使用自己传入的Looper对象创建Handler
         * Use the provided {@link Looper} instead of the default one and take a callback
         * interface in which to handle messages.  Also set whether the handler
         * should be asynchronous.
         * <p>
         * Handlers are synchronous by default unless this constructor is used to make
         * one that is strictly asynchronous.
         * <p>
         * Asynchronous messages represent interrupts or events that do not require global ordering
         * with respect to synchronous messages.  Asynchronous messages are not subject to
         * the synchronization barriers introduced by conditions such as display vsync.
         *
         * @param looper   The looper, must not be null.
         * @param callback The callback interface in which to handle messages, or null.
         * @param async    If true, the handler calls {@link Message#setAsynchronous(boolean)} for
         *                 each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
         * @hide
         */
        @UnsupportedAppUsage
        public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
            //相关属性赋值
            mLooper = looper;
            //获取消息队列
            mQueue = looper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    

    结论:所以从构造方法我们就可以知道

    • Handler中包含一个Looper,LooperQueue
    • 消息发送分为同步,与异步,异步情况用的少
    • looper分为自己传入,和Handler默认获取两种。

    Handler的创建既然已经搞清楚了,就在看看它的消息发送功能,发送功能只分析比较重要的几个方法

    sendMessageAtTime发送消息在某个时间点

    /**
         * 发送消息 在某个时间
         * Enqueue a message into the message queue after all pending messages
         * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
         * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
         * Time spent in deep sleep will add an additional delay to execution.
         * You will receive it in {@link #handleMessage}, in the thread attached
         * to this handler.
         *
         * @param uptimeMillis The absolute time at which the message should be
         *                     delivered, using the
         *                     {@link android.os.SystemClock#uptimeMillis} time-base.
         * @return Returns true if the message was successfully placed in to the
         * message queue.  Returns false on failure, usually because the
         * looper processing the message queue is exiting.  Note that a
         * result of true does not mean the message will be processed -- if
         * the looper is quit before the delivery time of the message
         * occurs then the message will be dropped.
         */
        public boolean sendMessageAtTime(@NonNull 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;
            }
            return enqueueMessage(queue, msg, uptimeMillis);//加入消息到队列
        }
    
    

    getPostMessage,将Runable转换成Message,相当于可以发送一个Runable接口,又相当于将一段Runable中运行的代码到消息队列中,又相当于这段代码运行的线程是在Looper所在的线程中。

     /**
         * 将Runable转换成Message的方法
         *
         * @param r 传入一个Runable接口
         * @return 返回一个Message对象
         */
        private static Message getPostMessage(Runnable r) {
            Message m = Message.obtain();
            m.callback = r;
            return m;
        }
    

    sendMessageAtFrontOfQueue发送消息到队列头部

    /**
         * 发送一个消息到队列最前面  uptimeMillis传0 即可
         * Enqueue a message at the front of the message queue, to be processed on
         * the next iteration of the message loop.  You will receive it in
         * {@link #handleMessage}, in the thread attached to this handler.
         * <b>This method is only for use in very special circumstances -- it
         * can easily starve the message queue, cause ordering problems, or have
         * other unexpected side-effects.</b>
         *
         * @return Returns true if the message was successfully placed in to the
         * message queue.  Returns false on failure, usually because the
         * looper processing the message queue is exiting.
         */
        public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
            MessageQueue queue = mQueue;
            if (queue == null) {
                RuntimeException e = new RuntimeException(
                        this + " sendMessageAtTime() called with no mQueue");
                Log.w("Looper", e.getMessage(), e);
                return false;
            }
            return enqueueMessage(queue, msg, 0);
        }
    

    enqueueMessage,加入消息到队列

        /**
         * 加入消息到队列
         * @param queue 消息队列
         * @param msg   消息体
         * @param uptimeMillis  发送时间
         * @return  是否加入成功
         */
        private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
                                       long uptimeMillis) {
            msg.target = this;
            msg.workSourceUid = ThreadLocalWorkSource.getUid();
    
            if (mAsynchronous) {
                msg.setAsynchronous(true); //设置消息是同步还是异步,这里可以看出,要么全是同步,要么全是异步
            }
            return queue.enqueueMessage(msg, uptimeMillis);//调用消息队列的enqueueMessage方法加入消息
        }
    

    Message的创建

        /**
         * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
         * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
         * If you don't want that facility, just call Message.obtain() instead.
         */
        @NonNull
        public final Message obtainMessage() {
            return Message.obtain(this);
        }
    

    结论

    • 各种sendMesssage方法最后都会调用到MessageQueue的enqueueMessage
    • 可以将Runable封装成Message,并发送到Looper线程处理,也有与Runable匹配的各种sendMessage方法。
      -Message的创建最好用Handler提供的obtainMessage()方法,这样创建的对象是从对象池中获取,减少开销。

    下图是sendMessage的一个调用链,便于理解

    消息发送方法链
    Handler可以sendMessage还可以处理消息dispatchMessage接下来看看处理消息相关分析
        /**
         * Handle system messages here.
         */
        public void dispatchMessage(@NonNull Message msg) {
            if (msg.callback != null) {//如果msg的callBack不为空则交给handleCallback方法处理
                handleCallback(msg);
            } else {
                if (mCallback != null) {//如果Handler的mCallback不为空,这交给mCallback处理
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);//都没人管交给Handler 的Handler处理
            }
        }
    

    handleCallback

       private static void handleCallback(Message message) {
            message.callback.run();
        }
    

    handler的handleMessage方法

        /**
         * Subclasses must implement this to receive messages. 常用就是通过重写该方法实现消息处理逻辑
         */
        public void handleMessage(@NonNull Message msg) {
        }
    

    Callback的上面已经写了就不说了。

    2.2 Message源码分析

    Message是消息传递的载体,可以理解成一个数据mode一样,下面来分析一下它的重要属性与重要方法,
    重要属性,常用的传输数据,比如arg,data,what,等我就不做说明了

        //每个Message持有发送Handler的引用,哪来干什么呢?当然是调用handler.dispatch来处理消息了
        @UnsupportedAppUsage
        /*package*/ Handler target;
        //上节讲了,用于将callBack变成Message
        @UnsupportedAppUsage
        /*package*/ Runnable callback;
        //这里next就代表一个链表,每个对象的next则指向它的下一个,当用于回收池时,next就指向下一个回收对象
        // 当用于MessageQueue,就指向下一个需要处理的message。
        // sometimes we store linked lists of these things
        @UnsupportedAppUsage
        /*package*/ Message next;
    
    
        /**
         * @hide 资源池的对象锁
         */
        public static final Object sPoolSync = new Object();
        //Message 池子
        private static Message sPool;
        //当前池子有的message数量
        private static int sPoolSize = 0;
        //池子最大值
        private static final int MAX_POOL_SIZE = 50;
        /**
         * 回收Message是否进行安全检查,默认为真
         */
        private static boolean gCheckRecycle = true;
    

    重要方法

    得到一个Message对象,其他几种方法都是调用这个方法得到message对象,并对Handler,callback,obj等属性赋值,就不说明。理解Mesage回收池是一个比较重要的地方,其中next的妙用,牛逼。

        /**
         * Return a new Message instance from the global pool. Allows us to
         * avoid allocating new objects in many cases.
         * 返回一个Message对象,从回收池中
         */
        public static Message obtain() {
            synchronized (sPoolSync) {
                if (sPool != null) {//回收池不为空
                    Message m = sPool; //spool对象给m
                    sPool = m.next;//spool的next变为链表第一个位置
                    m.next = null;//m对象next置空
                    m.flags = 0; // clear in-use flag
                    sPoolSize--; //线程池-1
                    return m;//返回message对象
                }
            }
            return new Message();
        }
    

    回收一个Message对象到回收池

    /**
         * 回收消息,当回收一个正在inUse的Message默认抛异常,gCheckRecycle默认为ture,5.0以前默认为false,以后默认为true,安全第一呀
         * Return a Message instance to the global pool.
         * <p>
         * You MUST NOT touch the Message after calling this function because it has
         * effectively been freed.  It is an error to recycle a message that is currently
         * enqueued or that is in the process of being delivered to a Handler.
         * </p>
         *
         */
        public void recycle() {
            if (isInUse()) {
                if (gCheckRecycle) {
                    throw new IllegalStateException("This message cannot be recycled because it "
                            + "is still in use.");
                }
                return;
            }
            recycleUnchecked();
        }
    
    
    /**
         * 不安全的回收Message方法,可能会回收一个处于in-use的Message
         * Recycles a Message that may be in-use.
         * Used internally by the MessageQueue and Looper when disposing of queued Messages.
         */
        @UnsupportedAppUsage
        void recycleUnchecked() {
            // Mark the message as in use while it remains in the recycled object pool.
            // Clear out all other details.恢复相关属性到默认值
            flags = FLAG_IN_USE;
            what = 0;
            arg1 = 0;
            arg2 = 0;
            obj = null;
            replyTo = null;
            sendingUid = UID_NONE;
            workSourceUid = UID_NONE;
            when = 0;
            target = null;
            callback = null;
            data = null;
            //这里说明一下,在完成一次回收后,sPool就变成刚刚回收的Message对象,而next就指向上一次的回收对象
            synchronized (sPoolSync) {
                if (sPoolSize < MAX_POOL_SIZE) {//回收池中数量小于Max才进行回收操作
                    next = sPool;//将当前线程池的Message对象赋值给next
                    sPool = this;//将需要回收的这个对象引用给回收池--至此回收完成,回收池数量+1,
                    sPoolSize++;
                }
            }
        }
    

    2.3 MessageQueue源码解析

    在Handler 中我们分析到sendMesage 最后调用到MessageQueue的enqueueMessage方法,那我们从这个方法开始分析。

     /**
         * 向messageQueue message
         *
         * @param msg  加入的消息
         * @param when 消息发送的时间
         * @return 是否加入成功
         */
        boolean enqueueMessage(Message msg, long when) {
            if (msg.target == null) {//说明必须要有target对象才能处理消息
                throw new IllegalArgumentException("Message must have a target.");
            }
            if (msg.isInUse()) {//message正在处理,重复发送某个Message对象可能会出现这个问题
                throw new IllegalStateException(msg + " This message is already in use.");
            }
    ,
            synchronized (this) {
                if (mQuitting) {//正在退出,将该msg回收,加入消息失败
                    IllegalStateException e = new IllegalStateException(
                            msg.target + " sending message to a Handler on a dead thread");
                    Log.w(TAG, e.getMessage(), e);
                    msg.recycle();
                    return false;
                }
    
                msg.markInUse();//标记当前msg正在使用中
                msg.when = when;//赋值消息处理时间
                Message p = mMessages;//这里的mMessage就是待处理的一个链表队列,
                boolean needWake;
                //当p为空 代表啥?代表该msg是MessageQueue队列收到的第一个消息,它还是空的,啥也没有
                //when==0 代表啥?从前面可知 当uptimeMillis为0,即现在的when,表示要把它放在队列最前面,
                //when<p.when  嘛意思? 意思很简单,我这个msg的执行时间比你p列表最前面的还要早,应该让我最先执行
                if (p == null || when == 0 || when < p.when) {
                    // New head, wake up the event queue if blocked.
                    //所以if成立的执行结果就很明显了,1.将msg对象放在链表的首位over~
                    msg.next = p;
                    mMessages = msg;
                    needWake = mBlocked;//是否需要唤醒
                } else {//执行这个Block啥意思?就是msg肯定不在链表前面了该给他找个合适的位置了,排序操作,排序条件when,
                    // 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;//链表交给prev
                        p = p.next;//链表的老二变老大
                        if (p == null || when < p.when) {//p==?啥意思,就是老二没有,循环结束 when<p.when啥意思?新的老二已经诞生了循环结束,哈哈
                            break;
                        }
                        if (needWake && p.isAsynchronous()) {
                            needWake = false;
                        }
                    }
                    //msg可能是老二,老三。。。总之他去了该去的地方,一路走好~~~至此加入message完成
                    msg.next = p; // invariant: p == prev.next
                    prev.next = msg;
                }
    
                // We can assume mPtr != 0 because mQuitting is false.
                if (needWake) {
                    nativeWake(mPtr);
                }
            }
            return true;
        }
    
    

    MessageQueue既然有了加入消息的方法,获取当前待处理的消息就必不可少了,接下来让我们看看MessageQueue的next方法如何提取消息
    不看不知道,一看吓一跳,next方法比enqueueMessage方法复杂多了.难道不是
    Message message=mMessages;
    mMessages=mMessages.next;
    这么简单吗,哈哈

     @UnsupportedAppUsage
        Message 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;//native消息计数
            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);
                synchronized (this) {
                    // Try to retrieve the next message.  Return if found.
                    final long now = SystemClock.uptimeMillis();
                    Message prevMsg = null;
                    Message msg = mMessages;
                    if (msg != null && msg.target == null) {//当target为null,查询异步消息
                        // Stalled by a barrier.  Find the next asynchronous message in the queue.找到异步消息,退出循环
                        do {
                            prevMsg = msg;
                            msg = msg.next;
                        } while (msg != null && !msg.isAsynchronous());//遍历msg获取到符合条件的异步消息
                    }
                    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 {//到时间了,找到了msg并返回
                            // 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;
                    }
    
                    // Process the quit message now that all pending messages have been handled.
                    if (mQuitting) {//正在退出,返回null
                        dispose();
                        return null;
                    }
    
                    // If first time idle, then get the number of idlers to run.
                    // Idle handles only run if the queue is empty or if the first message
                    // in the queue (possibly a barrier) is due to be handled in the future.
                    if (pendingIdleHandlerCount < 0
                            && (mMessages == null || now < mMessages.when)) {
                        pendingIdleHandlerCount = mIdleHandlers.size();
                    }
                    if (pendingIdleHandlerCount <= 0) {
                        // No idle handlers to run.  Loop and wait some more.
                        mBlocked = true;
                        continue;
                    }
    
                    if (mPendingIdleHandlers == null) {
                        mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                    }
                    mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
                }
    
                // Run the idle handlers.
                // We only ever reach this code block during the first iteration.
                for (int i = 0; i < pendingIdleHandlerCount; i++) {
                    final IdleHandler idler = mPendingIdleHandlers[i];
                    mPendingIdleHandlers[i] = null; // release the reference to the handler
    
                    boolean keep = false;
                    try {
                        keep = idler.queueIdle();
                    } catch (Throwable t) {
                        Log.wtf(TAG, "IdleHandler threw exception", t);
                    }
    
                    if (!keep) {
                        synchronized (this) {
                            mIdleHandlers.remove(idler);
                        }
                    }
                }
    
                // Reset the idle handler count to 0 so we do not run them again.
                pendingIdleHandlerCount = 0;
    
                // While calling an idle handler, a new message could have been delivered
                // so go back and look again for a pending message without waiting.
                nextPollTimeoutMillis = 0;
            }
        }
    
    

    2.4Looper源码解析

    Looper通过调用MessageQueue 的next方法获取到可以处理的message,并调用message.target.dispatch方法分发消息,完成消息处理最后的流程。接下来看看Looper的重要属性,与方法。

    重要属性

        // sThreadLocal.get() will return null unless you've called prepare().
        //ThreadLocal简称TLS线程本地存储区域,用于线程存储信息,通过get,set方法,这里被用来存储looper对象
        @UnsupportedAppUsage
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
        /**
         * 主线程looperd对象
         */
        @UnsupportedAppUsage
        private static Looper sMainLooper;  // guarded by Looper.class
        
        private static Observer sObserver;
        /**
         * 消息队列,用于获取笑嘻嘻
         */
        @UnsupportedAppUsage
        final MessageQueue mQueue;
        /**
         * looper所在的线程
         */
        final Thread mThread;
    

    重要方法
    Looper的创建

        /**
         * Looper初始化
         * @param quitAllowed
         */
        private static void prepare(boolean quitAllowed) {
            if (sThreadLocal.get() != null) {//一个线程只有一个Looper
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            sThreadLocal.set(new Looper(quitAllowed));//创建Looper并存储到TLS
        }
    

    Looper构造函数

        private Looper(boolean quitAllowed) {//创建Pooper
            mQueue = new MessageQueue(quitAllowed);//创建MessageQueue Looper是否允许退出
            mThread = Thread.currentThread();//当前线程
        }
    

    获取存储的looper对象

     /**
         * Return the Looper object associated with the current thread.  Returns
         * null if the calling thread is not associated with a Looper.
         * 从TLS中获取Looper对象
         */
        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }
    

    Loop方法循环拾取MessageQueue的Message,这里只取了关键代码部分,其他关于日志log的进行了删减

     for (; ; ) {//又见死循环
                Message msg = queue.next(); // might block  从Messagequeue中获取message
                if (msg == null) {//没有可以处理的消息,返回
                    // No message indicates that the message queue is quitting.
                    return;
                }
                msg.target.dispatchMessage(msg);//分发消息
     
                msg.recycleUnchecked();//消息分发完成,进行回收处理
            }
        }
    

    Looper的queit方法

      public void quit() {
            mQueue.quit(false);//安全退出
        }
       public void quitSafely() {
            mQueue.quit(true);不安全退出
        }
    

    MessageQueue的退出方法

        //
        void quit(boolean safe) {
            //当mQuitAllowed为false表示不能退出
            if (!mQuitAllowed) {
                throw new IllegalStateException("Main thread not allowed to quit.");
            }
    
            synchronized (this) {
                if (mQuitting) {//如果正在退出返回
                    return;
                }
                mQuitting = true;
    
                if (safe) {
                    removeAllFutureMessagesLocked();//移除所有未处理的消息
                } else {
                    removeAllMessagesLocked();//移除所有消息,包括处理中的
                }
    
                // We can assume mPtr != 0 because mQuitting was previously false.
                nativeWake(mPtr);
            }
        }
    

    总结:Handler(sendMessage)message=========>MessageQueue======>Loop(取出消息)=====》Handler (dispatchMessage)就分析完毕

    到这里Java层的Handler的消息机制差不多就清晰了。下面贴一张关系图便于理解。


    Handler机制

    相关文章

      网友评论

          本文标题:Handler 消息机制详解

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