Handler 消息机制详解

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机制
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345