Handler源码分析

    Handler在Android世界中使用是非常非常频繁的,网上也有大把的Handler相关的博客,但是看一万次博客,不如自己撸一次源码。Handler使用起来也非常简单,但是实现起来却并不简单,稍微有点开发经验的人都应该知道几个概念:Message,消息,信息的载体;MessageQueue,消息队列,所有的Message都发送到这里,等待统一处理;Looper,轮询器,从消息队列中获取消息.以一张简图来了解下他们之间的工作流程:
1517747002027.jpg

    下面我们以一个最简单的例子来研究下Hanlder的实现原理,其中也会涉及到Looper,Message,
MessageQueue,直接上例子:

Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
};
private void sendMessageByTPW(){
    Message msg = mHandler.obtainMessage();
    mHandler.sendMessage(msg);
}

    上面这个例子应该是自从改革开放以来最最最最简单的Handler使用场景了,首先是获取一个Message;其次调用Handler的sendMessage方法将这个Message发出去;看起来非常简单,但是实际上是比较复杂的,首先看看new Handler():

/**
  * Default constructor associates this handler with the {@link Looper} for the
  * current thread.
  *
  * 这是Handler的默认构造器,他和当前线程(创建Handler的线程)的Looper绑定
  *
  * If this thread does not have a looper, this handler won't be able to receive messages
  * so an exception is thrown.
  *
  * 如果此线程木有Looper,那么这个Handler就没办法接收Message,所以就抛个异常给你尝尝
  */
public Handler() {
    this(null, false);
}

    从注释可以看出,每个线程的Handler都有一个Looper对象,Handler在哪个线程创建,就和这个线程的Looper绑定;那么,Looper到底是什么鬼呢?他是Handler机制的动力所在;当Message发往MessageQueue之后,需要在另一侧将这个Message取出来交给Handler处理,就像往水流进水池里,如果没有出水口,这池水就是一潭死水,没有什么价值;Message就好比是水,MessageQueue就是水池,Looper就是抽水泵了,他将池子(MessageQueue)中的水(Message)抽出来,在别的地方(Handler)使用,这样的水(Message)才有价值.正是由于Looper的存在,Message才能一个个进入MessageQueue,然后由从MessageQueue出来,发往不同的handler处理.一个成功的Handler背后,一定有一个伟大的Looper在默默支撑着他.需要注意的是,不是说创建了一个线程,就一定有一个Looper,而是一个线程可以有一个Looper,是可以有,不是必须有;至于到底有没有,主要看你是否需要,对于Android应用的主线程,肯定是有一个Looper的;但是如果一个线程是我们自己创建的子线程,而且在此线程中压根就不需要创建和使用Handler,那么当然就不需要创建Looper了;如果需要Looper的话,就一定要先调用Looper.prepare().下面所有的流程,都以主线程为例进行分析,在子线程中创建Looper,就必须先显式调用Looper.prepare(),但是在主线程就不需要了,这个调用是由系统完成的,具体的调用地方是ActivityThread的main方法.接下来分析下带参数的Handler的构造函数:

/**
 * Use the {@link Looper} for the current thread with the specified callback interface
 * and set whether the handler should be asynchronous.
 *
 * 使用指定回调接口的当前线程的Looper,设置此Handler是应该异步调用
 *
 * Handlers are synchronous by default unless this constructor is used to make
 * one that is strictly asynchronous.
 * 
 * Handler默认是同步调用的,除非构造函数里面指定了参数要求异步调用
 *
 * 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(Callback callback, boolean async) {
    //如果FIND_POTENTIAL_LEAKS为true的话,就检测此Handler是否可能引起内存泄露
    //默认是false,所以不会提醒可能造成内存泄露,具体实现不用管.
    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());
        }
    }
    //调用myLooper获取当前线程的Looper
    mLooper = Looper.myLooper();
    //如果没有拿到Looper对象,也就是没有调用Looper.prepare(),那么死给你看
    //所以,在子线程中要拿到Looper对象,就一定要先调用Looper.prepare()
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    //每个Looper都有一个MessageQueue和他对于,在这里就拿到MessageQueue
    mQueue = mLooper.mQueue;
    //callback和async都是传进来的,一个是null,一个是false;前者表示不需要
    //回调,后者表示此Handler使用同步方式调用
    mCallback = callback;
    mAsynchronous = async;
}

    此时,系统中对象分布如下:
1517664647129.jpg

    Handler带参数的构造函数看起来不难,但是Looper.myLooper();其实挺复杂的:

/**
 * Return the Looper object associated with the current thread.  Returns
 * null if the calling thread is not associated with a Looper.
 *
 * 返回和调用myLooper的线程绑定的Looper对象.如果调用线程没和一个Looper
 * 绑定(可能是没调用Looper.prepare()),那么就返回null
 */
 public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

    myLooper方法看起来简单的掉渣,就是调用sThreadLocal的get方法,其实背后的实现一点都不简单,他涉及到java的一项技术:ThreadLocal.ThreadLocal这项技术在实际应用开发中并不很多,他实现了线程本地存储,具体来说,就是有一个ThreadLocal对象,这个对象可以被多个线程使用,但是每个线程从ThreadLocal拿到的同一类型的变量的属性值是不一样的,也就是这个值是线程级别的,不同线程的值不一样.我们先来看下sThreadLocal的定义:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    一个典型的泛型的使用,可以把ThreadLocal简单的理解成ArrayList那样的容器,里面装的元素就取决于怎么创建ThreadLocal的了,关于ThreadLocal在另一篇文章中分析过:https://www.jianshu.com/p/9ef748d40ef6;在上面的例子中,ThreadLocal装的是Looper对象,那么这些Looper对象是怎么放进去的呢?答案就在上面提到过的prepare方法,不过这个方法只会在子线程里面调用,Looper提供了一个prepareMainLooper方法,专门给主线程往ThreadLocal中添加Looper,prepareMainLooper方法是在ActivityThread方法里面调用的,ActivityThread就是我们常说的主线程,UI线程,但是他不继承自Thread类,在Android应用进程里面,看一个线程是不是主线程,就看他有没有调用prepareMainLooper,我们来看主线程是怎么调用这个方法的:

public final class ActivityThread {
    //ActivityThread是Object的子类,不是Thread的子类,切记
    //main函数,也就是这个类的入口函数,没什么好说的
    public static void main(String[] args) {
        ......
        Looper.prepareMainLooper();
        ......
    }
}

    下面看下prepareMainLooper的具体实现:

/**
 * Initialize the current thread as a looper, marking it as an
 * application's main looper. The main looper for your application
 * is created by the Android environment, so you should never need
 * to call this function yourself.  See also: {@link #prepare()}
 * 注释很简单,不额外翻译
 */
public static void prepareMainLooper() {
    //首先调用prepare,传入一个false,看来,主线程的Looper的
    //获取方式和子线程Looper的获取方式没什么两样,区别是一个
    //是系统调用,一个是开发者手动调用
    prepare(false);
    synchronized (Looper.class) {
        //如果sMainLooper已经被创建了,那么再次调用prepareMainLooper
        //就会抛出异常,所以prepareMainLooper只能调用一次
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        //调用myLooper获取一个Looper对象
        sMainLooper = myLooper();
    }
}

    先来看下prepare,看看他到底准备了些什么玩意:

public static void prepare() {
    prepare(true);
}
---------------------------------------
private static void prepare(boolean quitAllowed) {
    //sThreadLocal.get()就是获取一个Looper对象,如果在prepare的时候
    //发现当前线程的Looper对象已经创建,那么就抛出一个异常,也就是说
    //,prepare也只能调一次
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    //如果当前线程没有Looper对象的话,就创建一个,然后放入sThreadLocal中
    sThreadLocal.set(new Looper(quitAllowed));
}

    先来看下Looper的构造函数:

private Looper(boolean quitAllowed) {
    //构建一个MessageQueue,也就是消息队列,我们sendMessage的时候
    //,就是将消息发往消息队列的
    mQueue = new MessageQueue(quitAllowed);
    //获取创建Looper对象的线程
    mThread = Thread.currentThread();
}

    构建Looper的时候,就构建了一个消息队列MessageQueue,MessageQueue在整个Handler机制中也是很重要的,为了表示对他的尊重,来看下他的定义:

/**
 * Low-level class holding the list of messages to be dispatched by a
 * {@link Looper}.  Messages are not added directly to a MessageQueue,
 * but rather through {@link Handler} objects associated with the Looper.
 * 
 * MessageQueue是一个低层次的类,他持有由Looper分发的消息的列表。消息并不
 * 是直接添加到消息队列的,他是通过很Handler关联的Looper来添加的(从这也可
 * 以看出Looper的作用了)
 * <p>You can retrieve the MessageQueue for the current thread with
 * {@link Looper#myQueue() Looper.myQueue()}.
 * 开发者可以通过Looper的myQueue获取当前线程的消息队列
 */
public final class MessageQueue {
    MessageQueue(boolean quitAllowed) {
        mQuitAllowed = quitAllowed;
        //一眼就能看出,nativeInit在Native层创建了一个Native层的
        //对象,然后mPtr就是这个对象的地址
        mPtr = nativeInit();
    }
    ......  //暂不考虑其他的实现
}

    在MessageQueue的构造函数里面,通过JNI在Native层创建了一个对象,来看看创建的是什么鬼:

static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
    //创建一个NativeMessageQueue对象,从名字都能看出,这是位于Native层
    //的消息队列,也就是说,Java层的一个MessageQueue,在Native层有一个
    //NativeMessageQueue跟他对应,其实Handler的核心就在Native层,有这样
    //一个对象一点都不奇怪
    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
    if (!nativeMessageQueue) {
        jniThrowRuntimeException(env, "Unable to allocate native queue");
        return 0;
    }
    //增加对这个NativeMessageQueue对象的引用
    nativeMessageQueue->incStrong(env);
    //返回这个NativeMessageQueue对象的地址给Java层
    return reinterpret_cast<jlong>(nativeMessageQueue);
}

    此时,系统中对象分布如下:
1517664647129.jpg

再来看下NativeMessageQueue的构造函数:

NativeMessageQueue::NativeMessageQueue() :
        mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
    mLooper = Looper::getForThread();
    if (mLooper == NULL) {
        mLooper = new Looper(false);
        Looper::setForThread(mLooper);
    }
}

    可以看到,创建Native层的NativeMessageQueue的时候,同时创建了一个Native层的Looper对象,这个Looper对象的创建非常重要,一会分析.从上面的代码中可以看出,Native层的Looper对象也是和线程绑定的.

此时,系统中对象分布如下:
1517665664072.jpg

下面瞅瞅Native层Looper的构造函数:
Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
        mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    //调用eventfd创建一个事件对象,这个对象用来实现进程/线程间的等待/通知机制
    //eventfd返回的是一个文件描述符,6.0之前是通过管道的方式来创建的,用管道的
    //方式会涉及一个读端和一个写端;6.0开始改成eventfd了,据说是后者要高效点.
    //我们知道,消息被添加进消息队列后,要通知Looper,有消息可以获取了,这个通知
    //的过程,就靠下面的mWakeEventFd了
    mWakeEventFd = eventfd(0, EFD_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd.  errno=%d", errno);
    AutoMutex _l(mLock);
    //重建epoll,很重要的调用
    rebuildEpollLocked();
}

    Java层的Looper对象在创建的时候,会创建一个Java层的MessageQueue对象,MessageQueue对象又会在Native层创建一个NativeMessageQueue对象,然后将这个对象的地址返回给Java层的MessageQueue对象,NativeMessageQueue和MessageQueue是具有一一对应关系的.NativeMessageQueue对象在创建的过程中,会创建一个Native层的Looper对象,需要注意的是,ativeMessageQueue和MessageQueue具有一一对应关系,但是Java层和Native层的Looper是没有什么关系的,只是类型名字相同而已.Native层的Looper对象在创建的时候,会创建epoll文件句柄,epoll是Linux系统的一种通信机制,在Android中得到了大量的使用,所以简单研究下(可能存在表述不准确的情况,见谅,毕竟不是专业做linux开发的):

void Looper::rebuildEpollLocked() {
    // Close old epoll instance if we have one.
    //如果有老的epoll文件句柄,那么先关闭他
    if (mEpollFd >= 0) {
        close(mEpollFd);
    }
    // Allocate the new epoll instance and register the wake pipe.
    //首先创建一个epoll专用的文件描述符mEpollFd,epoll_create是
    //Linux系统的标准函数,不多分析(也没有能力分析,太菜)
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    //创建并初始化一个事件item,这个eventItem用来表达监听句
    //柄的诉求.比如监听哪个句柄,监听这个句柄上的什么事件
    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    //我们监听的是EPOLLIN事件,EPOLLIN事件就是指定的文件句柄有数据可读的事件
    eventItem.events = EPOLLIN;
    //更具体来说,关注的是mWakeEventFd这个文件上的EPOLLIN事件,
    //当mWakeEventFd有内容可读时,就唤醒相关线程进行读操作
    eventItem.data.fd = mWakeEventFd;
    //向epoll注册监听mWakeEventFd这个文件上的eventItem事件,EPOLL_CTL_ADD可以
    //理解成往epoll添加监听指定fd的指定的eventItem事件,也可以理解成注册监听
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
    //下面这块代码跟Native层的Message机制有关,跟我们分析的handler没什么关系,不管
    for (size_t i = 0; i < mRequests.size(); i++) {
        const Request& request = mRequests.valueAt(i);
        struct epoll_event eventItem;
        request.initEventItem(&eventItem);
        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
        if (epollResult < 0) {
            ALOGE("Error adding epoll events for fd %d while rebuilding epoll set, errno=%d",
                    request.fd, errno);
        }
    }
}

    到此为止,一个Handler才算是真正创建完成.简简单单的new Handler(),竟然牵扯出这么多知识点.在Java层创建一个Handler,在Native层创建了NativeMessageQueue,Looper,epoll文件句柄等。
Handler创建完后,就可以通过Handler获取一个消息了,下面分析消息是怎么获取的:

public final Message obtainMessage()
{
    //调用Message的obtain方法,传入的this是hanlder对象,这个参数很重要
    return Message.obtain(this);
}
-------------------------------------------------------
/**
 * 
 * Defines a message containing a description and arbitrary data object that can be
 * sent to a {@link Handler}.  This object contains two extra int fields and an
 * extra object field that allow you to not do allocations in many cases.  
 *
 * 定义一个发送给Handler的包含描述和任意数据对象的消息.这个对象包含了两个int类型
 * 和一个Object类类型的成员变量.这些变量并不是每次使用Message的时候需要使用的,其实
 * 就是Message的arg1,arg2和obj这三个变量,需要的时候就用,不需要的时候就不用管了
 *
 * <p class="note">While the constructor of Message is public, the best way to get
 * one of these is to call {@link #obtain Message.obtain()} or one of the
 * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
 * them from a pool of recycled objects.</p>
 *
 * 虽然Message的构造函数是公开的,但是获取Message的最好方式是调用Message的obtain方法或者
 * Handler的obtainMessage方法,因为这种获取Message的方法将从Message池中拿到一个Message,这
 * 种方法比较高效
 *
 */
public final class Message implements Parcelable {
    //可以看到,Message实现了Parcelable接口,那么每个Message都可以跨进程传输
    //可以看到,Handler的obtainMessage方法,最终还是调用Message的obtan方法,注意target = h
    //这个赋值很重要,因为不同Handler的Message要分发到各个不同的Handler,不能搞混了
    public static Message obtain(Handler h) {
        Message m = obtain();
        m.target = h;
        return m;
    }
}

    Message最终是通过obtain来获取的,下面分析obtain方法:

/**
 * Return a new Message instance from the global pool. Allows us to
 * avoid allocating new objects in many cases.
 *
 * 从全局的(消息)池中获取一个新的Message实例.从消息池中获取消息
 * ,很多情况下,能够避免新的对象的创建,估计跟线程池差不多的原理
 * ,预先创建一些Message,称之为消息池,当需要获取Message时,从消
 * 息池中拿出一个给调用者,池中的消息数量减一;当消息用完后,返回
 * 给消息池,这样可以避免频繁创建Message
 */
public static Message obtain() {
    //sPoolSync是一个final static类型的Object对象
    synchronized (sPoolSync) {
        if (sPool != null) {
            //消息池是以链表的形式存在,当需要获取新的消息时,将
            //链表头返回回去,然后将链表头z
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

    Message的获取过程分析完毕,挺简单的.下面来看下Handler是怎么发送消息的:

 /**
     * Pushes a message onto the end of the message queue after all pending messages
     * before the current time. It will be received in {@link #handleMessage},
     * in the thread attached to this handler.
     *  
     * 将一个Message推送到消息队列的末尾,消息队列是有顺序的,先推送的Message在队列的前面
     * 后推送的在队列的后面.这个Message将在Hanlder的handleMessage中被接收.
     *
     *
     * @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.
     *
     * sendMessage还有个boolean类型的返回值,不过一般无需关注
     */
    public final boolean sendMessage(Message msg)
    {
        //超简单的调用.这里也可以看出,任何发送消息都属于延时发送,只不过延时的
        //时间是多少而已.看来sendMessageDelayed才是隐藏在背后的大佬
        return sendMessageDelayed(msg, 0);
    }

    下面看下消息是怎么延时发送的:

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    //延时发送消息可以,但是请不要穿越.
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    //简单的调用sendMessageAtTime,把当前时间+延时时间传进去,也就是发送
    //消息的真正时间,如果没有延时的话,发送消息的时间就是当前时间,如果
    //有延时的话,发送消息的时间就是当前时间+指定的延时时间
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

    下面分析sendMessageAtTime方法:

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        //第一个参数是上面创建的消息Message;第二个参数是Message发送的时间
        //第一个重要的对象MessageQueue出现
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        //调用enqueueMessage讲Message推送到消息队列MessageQueue
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    分析完了sendMessageAtTime了,再来看下Message是入队的:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    //target就是一个Handler,也就是说这个Message是哪个Handler发送的,最后将由这个Handler
    //来处理这个Message,这也就是target的含义.enqueueMessage是Handler的方法,那么this
    //也就是调用enqueueMessage的Handler,最后调用这个Handler的handlerMessage来处理这个Message
    msg.target = this;
    //mAsynchronous是指此Handler是否是异步Handler,如果是的话,
    //那么需要将每个Message设置成异步消息
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    //调用MessageQueue的enqueueMessage方法,注意这个queue变量,他是MessageQueue
    //类型的,是Handler的成员属性,每个Handler的构造函数里面都会调用mLooper.mQueue
    //来初始化他,而mLooper也是在Handler的构造函数里面调用Looper.myLooper()初始化的
    //也就是说,一个Handler一旦创建,就会有一个Looper对象和一个MessageQueue对象和他
    //绑定在一起
    return queue.enqueueMessage(msg, uptimeMillis);
}

    下面来分析enqueueMessage方法:

boolean enqueueMessage(Message msg, long when) {
    //第一步就是判断target,也就是没有处理这个Message的
    //目标Handlder的话,直接抛出异常,这种情况很少见
    if (msg.target == null) {
        throw new IllegalArgumentException("Message must have a target.");
    }
    //从方法名来看,如果这个Message正在使用的话,那么抛出异常,后面碰到再分析
    //哪样才叫做InUse
    if (msg.isInUse()) {
        throw new IllegalStateException(msg + " This message is already in use.");
    }
    synchronized (this) {
        //mQuitting是在quit方法中设置成true的,从名字来看,应该是消息处理完了
        //了才调用,处理完了就退出,所以目前为止,mQuitting还是false的
        if (mQuitting) {
            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;
        }
        //markInUse的作用是给Message添加FLAG_IN_USE这个标记位,代表消息队列正在处理这个
        //Message了,这个Message已经被使用了,不能往消息队列推送这个消息了
        msg.markInUse();
        //设置消息发送的时间,when是之前的方法调用传进来的
        msg.when = when;
        //mMessages是消息队列的头,也就是消息队列第一个消息,代表接下来需要处理的消息
        //需要注意的是,mMessages只是指向了消息队列的头,如果需要,他还可以指向别的消息
        //p在这里其实就是一个中间变量,就像冒泡排序中引入的中间变量一毛一样
        Message p = mMessages;
        //是不是需要唤醒线程,因为消息队列一旦没有消息,获取消息的线程就会进入睡眠
        //状态,如果有新的消息到来,就需要把睡眠的线程唤醒,让他工作
        boolean needWake;
        //p == null意味着当前没有消息需要处理,when == 0意味着待处理的消息的发送时间是0,
        //0的概念就是立刻,马上处理;when < p.when意味着p是通过sendMessageDelay等方式发送
        //的消息,也就是有一个延时,而当前目标消息没有延时,这样的话,还没进入消息队列的消
        //息的when值可能比已经在消息队列的消息的when值小;第一种场景非常好理解,消息队列没
        //有消息,那么刚发的消息肯定位于队列头,这没毛病;需要注意到的是,消息队列的消息都
        //是按照发送时间先后(也就是when值大小)来排序,然后顺序处理的;消息队列只认消息携带
        //的when值,至于是否是真的先发送的消息,他其实不关心,已经位于消息队列的消息,在程
        //序员看来肯定是先发送的,但是一旦使用延时发送,那么消息队列就会认为这是以后将要发
        //送的消息,只是穿越了一下,提前进入了消息队列,尽管提前进入了消息队列,但是消息队
        //还是会把它排到后面处理.这个时候如果来了一个没有延时的消息,这个消息就会被插入延
        //时消息的前面,典型的插队行为,这就是if分支的作用
        if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                //目标消息要被插入消息队列头部了,马上要处理了,然后将原来的头部
                //消息赋值给next,原来的头部消息就等下次处理了
                msg.next = p;
                //将目标消息赋值给mMessages,代表接下来就处理这个消息
                mMessages = msg;
                //mBlocked代表了当前的线程状态,如果当前线程是睡眠的话,这个值
                //就是true,否则为false。如果线程处于睡眠状态,那么mBlocked就会
                //为true,此时就需要唤醒他,所以needWake跟着为true;反之就是false
                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.
                //将目标消息插入消息队列中间.通常我们是不需要唤醒事件队列的,除非队列头
                //有一个barrier,而且最早的消息是以异步消息加入队列的
                //if分支是插队的场景,这里是正常排队的场景,所以要确保这个消息被正确插入
                //正确的位置
                //是否需要唤醒.需要唤醒的条件有三个:第一个,线程处于休眠状态,这是废话,
                //没有睡,哪有醒;p.target == null这个判断需要额外解释,这个方法的第一个步
                //就是判断target是不是null,也就是看这个message的Handler是不是null,如果是的
                //话,那么就死给你看,流程根本走不到这里.那么这个p怎么可能会出现target为null
                //的情况呢?只怪我们太年轻,懂的太少!!!enqueueMessage不是将消息添加进消息
                //队列的唯一方法,postSyncBarrier也能将一个消息送入消息队列,不过这种消息是一
                //种特殊的消息,他就是一根搅屎棍,因为这种消息是没有相应的Handler处理他的,那
                //么这种消息一旦进入消息队列,Looper就拿他没辙了,因为取出来也不知道交给哪个
                //Handler处理,这样整个消息队列的就卡在这个消息上了,这种消息叫做栅栏消息.既
                //然这个杀千刀的栅栏消息有这样一个功能,那么肯定有移除这个消息的功能,实际上确
                //实有,removeSyncBarrier就可以将这根搅屎棍从消息队列里面移除掉,一旦栅栏消息
                //被移除,那么栅栏消息后面的消息就会陆续被继续处理.不过栅栏消息就算再叼,他也
                //是卡不住异步消息的,也就说说如果栅栏消息后面有一个异步消息的话,这个异步消息
                //就会被插入到栅栏消息的前面.所以p.target == null && msg.isAsynchronous()的意
                //思是如果当前消息队列的头是栅栏消息,那么后面的消息将会被卡住处理不了;如果此
                //时送入消息队列的消息是异步消息,因为栅栏消息是阻挡不了异步消息的步伐的,所以
                //此时需要唤醒线程处理这个异步消息,栅栏消息其实就是给消息队列上了一把锁,有时
                //候还是蛮有用的
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                //前一条消息,也是一个中间变量
                Message prev;
                //遍历所有的消息,将目标消息的when值和已经在消息队列的的消息的when
                //值挨个进行对比,一旦发现一个消息的when值比目标消息的when值大,那
                //么目标消息就会被插入这个消息的前面
                for (;;) {
                    //首先将头消息赋值给prev
                    prev = p;
                    //其次将头消息的下一条消息赋值给p
                    p = p.next;
                    //如果p == null,说明此时消息队列一共就一条消息,那就直接放在消息
                    //队列的第二位;如果when < p.when,那么说明遍历到的消息是延时发送
                    //的,那么msg就应该位于这条消息(p)的前面
                    if (p == null || when < p.when) {
                        break;
                    }
                    //如果需要唤醒,说明消息队列有杀千刀的栅栏消息;如果p是异步消
                    //息,那么在处理p的时候就会把线程唤醒,那么msg就没必要再去唤醒了
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                //for循环完成后,就为目标消息msg找到了正确的位置
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
            // We can assume mPtr != 0 because mQuitting is false.
            //如果确实需要唤醒的话,就调用nativeWake唤醒之,ptr上面分析
            //过,那就是Native层的MessageQueue的对象的地址.所谓的唤醒
            //仅仅是触发下面要分析的nativePollOnce结束等待
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

    下面以一张图说明栅栏消息的特性:
1517745987308.jpg

    到目前为止,enqueueMessage分析完毕,不算太难,真正难的地方是最后一个调用nativeWake;从上面的分析也可以看出,通过sendMessageDelay等方法发送的消息,并不是延时发送消息,而是指延时处理消息,一旦调用了sendMessageDealy等方法,消息会马上送入消息队列,但不是马上处理,所以延时的是处理,不是发送.下面分析下nativeWake的作用:

static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) { 
NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); 
//调用NativeMessageQueue的wake方法 
nativeMessageQueue->wake(); 
}

void NativeMessageQueue::wake() { 
//调用Native层Looper的wake方法 
mLooper->wake(); 
}

void Looper::wake() { 
uint64_t inc = 1; 
//所谓的wake,就是往mWakeEventFd这个文件句柄写入一个1,mWakeEventFd之前分析过 
//在创建Native层Looper的时候,通过eventfd创建过一个文件句柄,然后注册到epoll中 
//一旦mWakeEventFd一旦被写入内容,就会触发读端去读取mWakeEventFd里面的内容,这 
//里写入数据后,epoll就会触发读端读取事件 
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t))); 
if (nWrite != sizeof(uint64_t)) { 
if (errno != EAGAIN) { 
ALOGW("Could not write wake signal, errno=%d", errno); 
} 
} 
}

    nativeWake的作用就是往mWakeEventFd写入一个数据1,然后epoll就会触发读端去读取相应的事件,至于写的是什么数据,其实在这里并不重要,只要让epoll检测到mWakeEventFd被写入内容即可.Java层通过enqueueMessage发送一个消息后,再通过nativeWake通知epoll,消息队里已经有新的消息了,这样才算是一个完整的发送消息的流程.
    消息发出去后,Looper是怎么获取消息,然后交给相应的Handler的handleMessage方法处理呢?这就需要研究Looper的相关代码了.之前我们说过,我们研究的是主线程的Handler机制,那么再回去看下ActivityThread的代码:

public static void main(String[] args) {
    ......
    Looper.prepareMainLooper(); //之前分析过
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    //关键在这里
    Looper.loop();
}

    可以看到,在主线程的main方法里面调用了Looper的loop方法:

/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 *
 * 运行这个线程里面的消息队列.当循环结束后,一定要记得调用quit
 */
public static void loop() {
    //首先拿到Looper,myLooper的实现比较简单,不额外解释
    final Looper me = myLooper();
    //如果没拿到Looper的话,那只能死给你看了
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() 
            wasn't called on this thread.");
    }
    //拿到消息队列
    final MessageQueue queue = me.mQueue;
    ......
    //死循环,主线程的main方法里面调用了一个死循环的方法.这个死循环非常
    //重要;如果没有这个死循环,那么主线程的main方法就很快的退出了,主线
    //程的mian方法退出,那么这个应用就over了,所以这个死循环是不可缺少的
    for (;;) {
        //拿到下一条消息,也就是消息队列的头消息,可能造成阻塞
        //,这个调用是重中之重,一会分析
        Message msg = queue.next(); // might block
        //如果消息队列没有消息了,那么就退出去,整个应用也就over了
        //所以一般都不会走到这个分支里面去;正常情况下,要么阻塞在
        //next方法里面,要么就是获取到了消息,执行if后面的流程
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        //调用Handler的dispatchMessage分发消息,用脚趾头都能想到
        //,最后肯定调到了Handler的handleMessage方法
        msg.target.dispatchMessage(msg);
        .....
        //回收消息,然后执行下一次循环
        msg.recycleUnchecked();
    }
}

    loop方法,他的核心就是一个死循环,然后在这个死循环中不断调用next去消息队列里面获取消息;loop本身不难,但是他调用的next方法却不容易,下面分析这个重要的调用:

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.
    //mPtr就是Native层的MessageQueue对象的地址
    final long ptr = mPtr;
    //如果Native层的对象都没了,那就不用玩了,直接返回空消息
    if (ptr == 0) {
        return null;
    }
    //IdleHandler的作用当消息队列当前没有更多消息可以处理时,就做些别的事
    //这些别的事就定义在IdleHandler里面,pendingIdleHandlerCount就是这种
    //IdleHandler的数量,这事我们不关心
    int pendingIdleHandlerCount = -1; // -1 only during first iteration
    //下次调用nativePollOnce判断有没有可以处理的消息的时间
    int nextPollTimeoutMillis = 0;
    //又一个死循环,死循环里面套着死循环
    for (;;) {
        //不懂
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }
    }
    //判断有没有消息可以处理,这里会造成阻塞,如果消息队列有消息需要处理,那
    //么这个方法就会返回,然后执行下面的流程,如果没有的话,就阻塞在这里;
    nativePollOnce(ptr, nextPollTimeoutMillis);
    synchronized (this) {
        final long now = SystemClock.uptimeMillis();
        Message prevMsg = null;
        //mMessages之前分析过,他指向了消息队列的头消息
        Message msg = mMessages;
        //if分支就是之前分析过的杀千刀的栅栏消息的场景
        if (msg != null && msg.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());
        }
        if (msg != null) {
            //如果头消息的when值比当前的时间大,说明这个消息是延时发送,那么还不到处理
            //这个消息的时候,所以先确定什么时候处理这个消息,给nextPollTimeoutMillis
            //赋值
            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;
                //如果msg的前一个消息不为null,那么将前一个消息的next指向
                //msg的next;因为msg要被拿出去处理了,这样的话,链表就断开
                //了,if分支的赋值能够把链表重新接上
                if (prevMsg != null) {
                    prevMsg.next = msg.next;
                } else {
                    //如果prevMsg为null,说明目标消息就位于队列头,那么这个
                    //消息的下个消息就是队列头了,这就是下面的赋值的作用
                    mMessages = msg.next;
                    //将msg的下个消息赋值为null,这样就把msg从队列里面摘了出来
                    msg.next = null;
                    //给这个消息添加FLAG_IN_USE标记位
                    msg.markInUse();
                    //返回这个消息
                    return msg;
                }
            }
        }else {
            // No more messages.
            //如果进入else,说明消息队列没有消息,那么将
            //nextPollTimeoutMillis设置成-1,代表无限期阻塞
            nextPollTimeoutMillis = -1;
        }
        //如果要退出Handler的话,那么销毁Native层的MessageQueue
        if (mQuitting) {
            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.
        //如果消息队列是空的,或者消息队列有消息,但是还没到处理的时间
        //那么就处理IdleHandler
        if (pendingIdleHandlerCount < 0
                && (mMessages == null || now < mMessages.when)) {
            pendingIdleHandlerCount = mIdleHandlers.size();
        }
        //如果没有IdleHandler,那么就阻塞一下下,将mBlocked置成true
        if (pendingIdleHandlerCount <= 0) {
            // No idle handlers to run.  Loop and wait some more.
            mBlocked = true;
            continue;
        }
        //初始化一个IdleHandler数组mPendingIdleHandlers
        if (mPendingIdleHandlers == null) {
            mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
        }
        mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
        //遍历各个IdleHandler,让他们跑起来,不是重点,不做详细分析
        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;
    }
}

    next也不是太难,真正难的是nativePollOnce,如果nativePollOnce执行完毕了,说明消息队列有消息了,那么就从消息队列里面获取消息;除了使用nativePollOnce方法获知消息队列有没有消息外,其实还有别的方案,比如Java层里面往死里轮询消息队列,看看有没有消息,但是这种方法比较低效,经常做无用功,无端消耗CPU资源,划不来,所以整出nativePollOnce这套机制,从名字也可以看出,在Native层轮询一次.下面分析下这个方法:

static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jlong ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    //调用NativeMessageQueue的pollOnce方法
    nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
----------------------------------
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
    mPollEnv = env;
    mPollObj = pollObj;
    //调用Native层Looper的pollOnce
    mLooper->pollOnce(timeoutMillis);
    mPollObj = NULL;
    mPollEnv = NULL;
    if (mExceptionObj) {
        env->Throw(mExceptionObj);
        env->DeleteLocalRef(mExceptionObj);
        mExceptionObj = NULL;
    }
}
----------------------------------
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    //pollOnce也是一个死循环,Handler机制到处可见死循环
    for (;;) {
        //这个是Native层的Handle,Message相关处理,不管
        while (mResponseIndex < mResponses.size()) {
            const Response& response = mResponses.itemAt(mResponseIndex++);
            int ident = response.request.ident;
            if (ident >= 0) {
                int fd = response.request.fd;
                int events = response.events;
                void* data = response.request.data;
                if (outFd != NULL) *outFd = fd;
                if (outEvents != NULL) *outEvents = events;
                if (outData != NULL) *outData = data;
                return ident;
            }
        }
        //上面刚申明了result = 0,所以这个分支暂时不进,但是if下面的流
        //程可能会改变result的值,如果改变了,就靠if分支退出这个方法了.
        if (result != 0) {
            //如果下面的pollInner方法返回了,那么先清理一些变量
            //接着返回result,这个方法能不能返回,Java层能不能去
            //消息队列拿消息,全指望pollInner了,pollInner要争气啊
        if (result != 0) {
            if (outFd != NULL) *outFd = 0;
            if (outEvents != NULL) *outEvents = 0;
            if (outData != NULL) *outData = NULL;
            return result;
        }
        //这才是重点
        result = pollInner(timeoutMillis);
    }
}

    可以看到,Java层调用一次nativePollOnce,Native层就会进入死循环,在死循环里面调用pollInner去做一些操作,如果这个方法返回了,那么下次循环就可以退出pollOnce方法了,如果pollOnce方法退出了,那么Java层的nativePollOnce也就返回了,nativePollOnce方法返回,Java层就可以愉快的去消息队列拿消息了,美滋滋.下面看下pollInner这个重要的方法的实现:

int Looper::pollInner(int timeoutMillis) {
    // Adjust the timeout based on when the next message is due.
    //timeoutMillis是Java层传下来的变量,代表阻塞时间;如果为0,说明不阻塞,方法
    //调用后立马返回;如果是-1,说明无限阻塞,只有Native层的mWakeEventFd被写入数据
    //后才返回;如果大于0,说明在指定的timeoutMillis之间之后就返回
    //下面是根据timeoutMillis处理超时时间,也就是说,timeoutMillis秒后,不管
    //mWakeEventFd有没有数据,都返回,这种场景常见于延时消息,也就是当前时间
    //不是处理消息的时间,得等等,这个等就是在Native层等
    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
        if (messageTimeoutMillis >= 0
                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
            timeoutMillis = messageTimeoutMillis;
        }
    }
    // Poll.
    //result是最终要返回的结果
    int result = POLL_WAKE;
    //mResponses和Java层的Handler无关,不管
    mResponses.clear();
    mResponseIndex = 0;
    // We are about to idle.
    //开始轮询,其实就是等待epoll的通知,不是真的轮询,此时是idle状态
    mPolling = true;
    //构建一个事件的结构体
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    //等待注册在mEpollFd上的文件句柄的事件的产生,timeoutMillis是超时时间,整个Handler
    //的阻塞,其实就是阻塞在epoll_wait这个方法里面;如果timeoutMillis为0,说明不阻塞,
    //立马返回,返回的事件信息就被写在eventItems中,拿到eventItems后,就可以解析里面
    //的信息,并返回了;如果timeoutMillis大于0,那么说明过了timeoutMillis之后返回,事
    //件信息同样被写在eventItems中;如果timeoutMillis为-1的话,那就是永久阻塞了;那么肯
    //定有退出阻塞状态的机制,到底是什么机制呢?就是上面分析过的nativeWake,这个方法在
    //Native层会往mWakeEventFd写入一个1,之前分析过;当mWakeEventFd被写入数据后,epoll
    //就会检测到,epoll_wait方法就会返回了.epoll使用的是回调,不会占用过多CPU
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    // No longer idling.
    //epoll通知了,退出轮询状态(尽管实际上不是真的轮询,但是变量名取的就是轮询,没办法)
    mPolling = false;
    // Acquire lock.
    //上锁
    mLock.lock();
    //什么玩意?不懂
    if (mEpollRebuildRequired) {
        mEpollRebuildRequired = false;
        rebuildEpollLocked();
        goto Done;
    }
    // Check for poll error.
    //如果eventCount小于0,说明内部发生错误,不考虑这种场景
    if (eventCount < 0) {
        if (errno == EINTR) {
            goto Done;
        }
        ALOGW("Poll failed with an unexpected error, errno=%d", errno);
        result = POLL_ERROR;
        goto Done;
    }
    // Check for poll timeout.
    //如果eventCount等于0,说明阻塞超时,不考虑这种场景
    if (eventCount == 0) {
        result = POLL_TIMEOUT;
        goto Done;
    }
    //正常情况下,会走下面的流程
    for (int i = 0; i < eventCount; i++) {
        //获取产生此事件的文件句柄
        int fd = eventItems[i].data.fd;
        //获取此文件句柄上发生的事件类型
        uint32_t epollEvents = eventItems[i].events;
        //如果发生事件的文件句柄是mWakeEventFd的话,进if分支
        //上面分析过,我们注册的就是mWakeEventFd这个文件上的监听
        //所以分析if分支即可
        if (fd == mWakeEventFd) {
            if (epollEvents & EPOLLIN) {
                //醒来
                awoken();
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
            }
        } else {
            ......  //who care
        }
    //搞定
    Done: ;
    .....   
    return result;
}

    下面看下awoken是怎么执行的:
    从上面的分析流程来看,当往消息队列发送一个消息时,就可能会调用nativeWake,这个方法的实现是往mWakeEventFd写入数据,至于是写入什么数据,不重要,重要的是写就可以了;往mWakeEventFd写入数据后的作用就是让MessageQueue的next方法中的nativePollOnce返回,简单来说,nativeWake就是通知MessageQueue有消息来了,赶紧让你家Looper把他取出来拿去处理吧.具体的流程是往mWakeEventFd写入数据后,Looper.cpp的pollInner方法中的epoll_wait就退出了阻塞状态,可以返回了;pollInner返回后,Looper.cpp的pollOnce方法也就返回了(pollOnce方法是一个死循环,肯定需要一个退出,返回机制);pollOnce返回后,Java层的nativePollOnce也就退出阻塞状态返回了,nativePollOnce返回后,MessageQueue的next方法就可以往下走了,下面的流程就是获取消息队列的消息.
    当然了,nativeWake可能不会调用,如果不调用的话,说明Java层的Looper正在有条不紊的取出Message并交给相应的Handler处理;这个时候发送一个消息,肯定也会被Looper拿到;只要Looper没有阻塞,消息队列的消息就会被Looper拿到并交给相应的Handler处理;如果Looper阻塞了,那么就调用nativeWake让Looper从阻塞状态醒来.
    拿到消息后,必须交给相应的Handler处理,这个流程就靠dispatchMessage方法实现了:

public void dispatchMessage(Message msg) {
    //Message的一个回调,如果设置了这个回调,那么调用handleCallback
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        //如果消息没有回调,但是Handler有回调的话,就调用回调的handleMessage
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        //如果没有任何回调的话,直接调用Handler的handleMessage,这个方法在Handler
        //是个空实现,这就是为什么我们用Handler的时候要重写handleMessage的原因
        handleMessage(msg);
    }
}

    到这里为止,Handler机制粗略的分析了一遍.整个Handler机制分为Java层和Native层,Java层的流程非常简单;难的是Native层,具体来说是epoll机制,epoll机制是Linux系统的一种机制,对于Android应用开发来说,理解起来有点麻烦,毕竟我们更多的是做应用,跟Java代码打交道,对Linux不输,包括我自己,对于epoll也不理解,有志于成为大神的人可以自己去研究epoll.Native层的作用就是告诉MessageQueue,消息队列的Java层基本分析完毕;Handler将Message送入消息队列后,Looper就不停的从消息队列获取Message,然后调用dispatchMessage,最后将Message分发给相应的Handler处理.从上面可以看出,在获取消息队列的时候,会在nativePollOnce被阻塞住,也就说,如果nativePollOnce没有返回的话,就不会执行下面的获取下一条消息流程;nativePollOnce返回了,就说明消息队列有消息了,Looper就可以拿到这些消息;如果没有返回,就说明消息队列没有消息,或者有消息,但是还不到处理的时间.如果发送一条消息到消息队列,那么怎么使nativePollOnce返回呢?也就是说Looper怎么知道消息队列有消息了?这就要回头看enqueueMessage方法了,之前分析过,这个方法的作用是将一条消息发送到消息队列,发送完了之后,这个方法还做了另一个动作:nativeWake,这个方法就可以将Looper从阻塞状态唤醒,也就是说这个方法可以通知Looper,有新的消息到来了,赶紧喊Looper过来处理.
    以上所有流程,本人并不能保证说的全对,限于能力,难免有理解不到位甚至是错误的地方,欢迎指正.

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

推荐阅读更多精彩内容