Handler消息机制源码全量解析

Handler消息机制源码解析

Android版本: 基于API源码26,Android版本8.0。java

本片文章的目的在于全面的了解Handler。它是如何传递消息的?是如何阻塞和唤醒线程的(仅限于Java层面)?MessageQueue究竟是怎么存储和取出Message?延迟消息是怎么被发送的?android

一 Handler定义:

Handler是一套消息传递的机制。设计用来让工做线程跟主线程之间进行消息传递。同时也解决了多线程同时更新UI的问题。Android系统设定子线程是不能更新UI的,当子线程必定要作更新UI的操做时,可使用Handler将消息从子线程带到主线程,并能保证消息的同步性。git

二 基本用法:

  1. 在主线程中使用:github

    //实例化Handler对象。
    Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
    };
    //建立并发送消息
    Message obtain = Message.obtain();
    obtain.what = 100;
    handler.sendMessage(obtain);
    
    复制代码
  2. 在子线程中使用,一旦使用该子线程是不会自动结束的,除非手动结束:json

    //为子线程中建立Looper对象。
    Looper.prepare();
    //实例化Handler对象。
    Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
    };
    //建立并发送消息。
    Message obtain = Message.obtain();
    obtain.what = 100;
    handler.sendMessage(obtain);
    //开启消息循环。
    Looper.loop();
    复制代码

若是先调用Looper.prepare()、Looper.loop()再handler.sendMessage(obtain),那么消息会成功的发送成功吗?api

三 源码解析:

Handle的消息传递过程当中涉及到了几个重要的类:Handler、Message、Looper、MessageQueue。缓存

  • Handler安全

    官方的解释:Handler容许您发送和处理MessageMessageQueue有关联的可运行对象Runnable。每一个Handler实例都与一个线程和该线程的消息队列关联,在建立的时候就会直接关联起来。Handler将Message和Runnable传递到消息队列中,并在它们从消息队列中出来时执行它们。多线程

    Handler被用在两个主要的地方:让Message和Runnable定时执行;在非UI线程中将Message或者Runnable发送到主线程。并发

    当应用程序建立进程时,其主线程专用于运行消息队列,该队列负责管理顶级应用程序对象(activities、broadcast receivers等)及其建立的任何窗口。

    也就是Handler是用来专门发送和处理消息的。发送是只发送到对应的消息队列就行了。

  • Message:

    官方解释:定义包含描述和可发送到{@link handler}的任意数据对象的消息。此对象包含两个额外的int字段和一个extra对象字段,在许多状况下容许您不进行分配。

    也就是Message是Handler传递的元数据,其内部能够包含不少信息:what、arg一、arg2,、obj等。Handler发送的也是Message对象,处理的也是Message对象。因此Message确定是序列化的,继承自Parcelable。内部维护了一个缓存池,避免建立多余的消息对象,缓存池的设计是Android系统源码一向的做风,在ViewRootImpl处理点击消息的时候,也有相似设计。该缓存池的大小为50,超过该缓存就会直接建立Messsage对象。

  • Looper:

    官方解释:Looper类用于为线程运行消息循环。默认状况下,线程没有与之关联的消息循环;若要建立一个消息循环,请在要运行该循环的线程中调用 prepare()方法,而后调用loop()使其处理消息,直到循环中止。

    也就是Handler只是将Message数据放到了MessageQunue中,Looper才是从MessageQunue中取出消息,并将消息发送到正确的Handle中去。一个线程中存在一个Looper,Looper中维护着MessageQueue。Looper.prepare()方法是建立Looper跟MessageQueue,再发送消息以后调用Looper.loop()方法,开启消息循环,也就是不停的从消息队列中那出消息处理。

  • MessageQueue:

    该机制中核心的存在。主要是用来操做Message的,实际上内部并无一个集合或者队列去存储Message,而是由Message组成的单链表结构。在Message的内部有个next属性,属性声明为Message对象,也就是Message自身就可组成一个队列。MessageQunue的目的就是增删对比Message。好比:第一个Message对象来了(m1),那么它的next属性是空的,而后又来了一个Message(m2)。发现m1还没执行完毕,那么就将m2的对象赋值给m1的next属性,当m1执行完毕以后,取出本身的next属性,若是不为null,那就接着执行next属性表示的Message,也就是m2。

当了解完每一个类的职责以后,发送的消息的流程就会清晰的不少。

通常的,一个Thread应该只有一个Looper和MessageQueue。能够有多个Handler对象。当你在主线程中建立Handler的时候,你是不须要调用Looper.prepare()的,由于主线程已经建立过了。建立Looper的线程决定了消息最终是在那个线程中被处理的。你在子线程中使用Handler对象发送消息,若是你的Looper是主线程中建立的,那么处理消息的仍是在主线程中,你发送消息的线程环境是可有可无的。

Handler建立源码解析:

Handler类是个普通的Java类,能够被继承。建立方式为:

//通常经过new的方法去建立。
Handler handler = new Handler();
复制代码

Handler有七个构造方法,三个是被隐藏掉的。被注解@hide注释以后,经过api是访问不到的:

//Handler.java 
    public Handler() {
        this(null, false);
    }
    public Handler(Callback callback) {
        this(callback, false);
    }

    public Handler(Looper looper) {
        this(looper, null, false);
    }

    public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }
   /** * @hide */
    public Handler(boolean async) {
        this(null, async);
    }

   /** * @hide */
    public Handler(Callback callback, boolean async) {
        //。。。省略代码
        //获取Looper对象。
        mLooper = Looper.myLooper();
        //。。。省略代码
        //获取MessageQueue。
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

    /** * @hide */
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

复制代码

能够看到构造参数中能够传入的类型:Callback接口,Looper对象,布尔值async。首先Callback接口也是处理消息的:

//Handler.java 
public interface Callback {
        /** * @param msg A {@link android.os.Message Message} object * @return True if no further handling is desired */
        public boolean handleMessage(Message msg);
}
复制代码

Handler类内部也有handleMessage()方法,使用的时候彻底能够重写该方法。Handler又提供该接口的目的也就是你能够不用实现Handler类中的方法也能处理消息,这样自由一点。

若是构造方法中你传入了Looper对象,就不须要去建立Looper对象了。至于布尔值async则是决定当前发送的Message是不是异步的消息,异步消息能够不受同步屏障的影响。在ViewRootImpl接收到绘制信号的时候,就会在UI Handler中发送一个同步屏障,这将阻止当前Handler处理全部的同步消息,而后让该此异步消息先执行。Handler的建立过程很简单,接下来看Message的建立过程。

Message建立源码解析:

Message类是final的不能被继承。实现了Parcelable接口。Message并无特殊的构造方法,因此直接就可new出来:

Message message = new Message();
复制代码

另外系统推荐的获取Message的方法为:

Message obtain = Message.obtain();
复制代码

obtain()方法有不少的重载方法,根据参数的不一样构造不一样的Message对象。该过程都是在Message内部实现的,对于调用着来讲是透明的,下面来分析下基础的obtain()方法:

//Message.java。
public static Message obtain() {
        synchronized (sPoolSync) {
            //判断缓存池是否为null。
            if (sPool != null) {
                Message m = sPool;
                //取出一个Message。
                sPool = m.next;
                m.next = null;
                //默认的flag为0。
                m.flags = 0; // clear in-use flag
                //大小减一。
                sPoolSize--;
                return m;
            }
        }
        //不然就new一个
        return new Message();
    }
复制代码

sPool是一个Message对象,至关于缓存队列的头指针。Mesage有个next属性,该属性仍是Message对象。当调用该方法的时候,就从sPool中取出下一个Message也就是m.next,而后将m.next赋值给sPool,也就是重置队列头,而后返回以前的队列头m。这种是典型的单向链表结构,Android系统的源码中不少地方都用到。而后在Message的reaycle()方法中,将使用过的Message存放到sPool表明的队列中。

//Message.java。
public void recycle() {
        if (isInUse()) {
            return;
        }
        recycleUnchecked();
    }

    void recycleUnchecked() {
    //。。。省略代码
        synchronized (sPoolSync) {
            //判断缓存的数量是否小于规定值的
            if (sPoolSize < MAX_POOL_SIZE) {
                //将队列头指针指向下一个元素
                next = sPool;
                //队列头重置,这样新的消息就变成了队列的第一个元素,以前sPool表示的消息就变成该消息的next。
                sPool = this;
                sPoolSize++;
            }
        }
    }
复制代码

Message的建立很简单,须要注意的就是这个缓存池的原理。

消息发送流程源码解析:

Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            return false;
        }
    });

 Message obtain = Message.obtain();
 obtain.what = 100;
 handler.sendMessage(obtain);
复制代码

上述代码便可发送一个消息数据。无论是sendMessage()仍是sendMessageDelayed()或者sendEmptyMessage()方法,最终都是调用的sendMessageAtTime()方法,sendEmpty***系列是Handler本身建立了一个空的Message,只是在使用着看起来是发送了一个空的消息同样,这里再也不分析:

//Handler.java。
public boolean sendMessageAtTime(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);
    }
复制代码

该方法中只是判断了MessageQueue是否为null。

//Handler.java。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
       //该消息的目标Handler为当前发送消息的Handler。
        msg.target = this;
        //若是是异步消息的话就设置为异步标记。
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
复制代码

对Message对象作了一些标记以后就调用了MessageQueue的enqueueMessage()方法,这两个标记都是很重要的,一个是设置目标Handler,这样消息就不会让错误的Handler处理。另一个是代表消息是不是异步的,通常使用的时候都是同步消息,UI线程毕竟是线程不安全的:

//Message.java。 
public void setAsynchronous(boolean async) {
        if (async) {
            flags |= FLAG_ASYNCHRONOUS;
        } else {
            flags &= ~FLAG_ASYNCHRONOUS;
        }
    }
复制代码

接着看queue.enqueueMessage()方法:

//MessageQueue.java。
boolean enqueueMessage(Message msg, long when) {
       //若是消息没有目标Handler就抛出异常。
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        //消息正在处理中 也抛出异常。
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
       //作了同步处理
        synchronized (this) {
            //当前的消息队列已经结束了。mQuitting = true。
            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;
            }
            //标记正在处理中
            msg.markInUse();
            //消息的倒计时,多久以后发出。
            msg.when = when;
            //mMessages表示当前准备处理消息。
            Message p = mMessages;
            boolean needWake;
            //1.当前要处理的消息为null。2.须要立刻发送,延迟时间为0。3.若是当前要处理的消息的延迟比正在处理的消息时间段。
            //上面三个条件知足一个就执行。若是是第一条消息if确定会执行,若是来了第二条Message,可是第一条Message还没执行完,也就是mMessages不为null,消息的when还等于0,那么也要直接执行,也就是添加到队列的头部。因此markInUse()方法仍是颇有必要的。
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                //当下一条消息来的时候发现前面还有消息没执行完,而且当前的消息也不是立马就执行的,或者等待的时间比正在执行的消息要长,那么就执行到这边。
               
                //p.target == null表示当前的消息是一个同步屏障。
                //needWake = true,说明当前的前一条消息是个同步屏障,而且当前的这条消息是个异步消息。
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                //这个死循环是为了找出队列中是否还有异步消息。
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    //若是当前的对列中还存在异步消息,那就不用立马唤醒线程,等待前一个异步消息执行结束。
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
            //插入队列中间。一般咱们没必要唤醒事件队列,除非队列的开头有一个屏障,而且消息是队列中最先的异步消息。 
            //判断是否唤醒线程。
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }
复制代码

上面的入对列操做很复杂:

  1. 一条新的消息到了,调用消息的markInUse方法。
  2. 判断是否要立马执行该消息。条件有三个:当前要处理的消息为null;延迟时间为0;若是当前要处理的消息的延迟时间比正在处理的消息时间短。
  3. 知足步骤2的三个条件,就将当前的消息放到消息对列的头部位置。needWake变量赋值。
  4. 当一条新的消息到来的时候,不知足步骤2,也就是当前有正在执行的消息,而且该消息须要延迟发送,延迟的时间还比较长。那么就会执行else方法。
  5. 走到else方法中,要先判断当前正在执行的Message是不是一个同步屏障,也就是 p.target == null,而后判断当前的消息是不是一个异步消息,由于异步消息的话,是须要立马执行的。而后有个For循环,判断当前的队列中是否有个异步消息还在处理中,有的话也就是 if (needWake && p.isAsynchronous())会执行,那么此条消息就不能立马执行。不然就要加入到队列中等待了。
  6. 判断needWake,是否唤醒线程。

通过上面的步骤,Handler将发送的Message放入到了消息队列中。Handler类的职责已经结束了。下面来看Looper到消息队列中取数据。

Looper源码解析:

Looper类的注释中说明了,在使用的时候要先调用Looper.prepare()方法,最后调用Looper.loop()方法。下面先看下prepare()方法:

//Looper.java。
   //该方法是能够在任何线程中调用。
   public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
    //该方法在ActivityThread建立的时候会被调用。
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
复制代码

prepare()系列方法就是建立一个Looper对象。采用prepareMainLooper()方法建立的Looper不会终止消息循环,其余的均可以被终止掉,也就是quitAllowed = true/fasle的问题。Looper建立结束以后看下loop()方法:

//Looper.java。
public static void loop() {
        final Looper me = myLooper();
         //。。。省略日志代码
        //Handler跟Looper用的是同一个队列。
        final MessageQueue queue = me.mQueue;
        //确保此线程的标识是本地进程的标识,并跟踪该标识令牌的实际内容。
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            //从消息队列中取出下一条消息。
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            //。。。省略日志代码
            try {
                //msg.target就是Handler,而后分发消息。
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
              //。。。省略日志代码
            }
           //。。。省略日志代码
            //消息处理结束以后回收消息。
            msg.recycleUnchecked();
        }
    }
复制代码

loop()方法要作的就是不停的从MessageQueue中获取消息,因此就使用了For死循环。拿到消息以后,开始分发消息,最后将消息回收。重点在于Message的next()和Handler的dispatchMessage()以及最后Message的recycleUnchecked()方法了。先看next()方法:

//MessageQueue.java
Message next() {
        //若是消息循环已经退出并被释放,则返回此处。若是应用程序在退出后尝试从新启动不受支持的循环程序,则可能发生这种状况。
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }
        //空闲时待处理的IdleHandler的数量。默认为-1。
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        //下次轮询超时毫秒
        int nextPollTimeoutMillis = 0;
        //开启死循环。要么阻塞,要么获取到Message。
        for (;;) {
            //将当前线程中挂起的任何绑定器命令刷新到内核驱动程序。在执行可能会阻塞很长时间的操做以前调用,以确保已释听任何挂起的对象引用,以防止进程占用对象的时间超过所需时间,这将很是有用。
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            //该方法可能会被阻塞,nextPollTimeoutMillis = -1的时候,将无限期的阻塞。也就是说当该方法有返回值的时候,那就表明该过程不会被阻塞,也就是会执行下面的代码逻辑,也就是将会至少取出一个消息。
            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // 获取系统时间。
                final long now = SystemClock.uptimeMillis();
                //该Message是表示将被执行的消息的前一个消息,有多是从消息队列的中间取出一个消息执行,这样须要将被取出消息的next拼接到被取出消息的上一个消息的next上,这样队列不会被断开。
                Message prevMsg = null;
                //队列的头消息。每次取出一个消息的时候都会将mMessages指向新的消息。
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                   //执行到这里说明当前的消息是一个同步屏障,也就是将阻止全部的同步消息。
                   //找出队列中的第一个异步消息,没有异步消息msg就是null。 
                    do {
                        //找出消息的上一个消息。
                        prevMsg = msg;
                        //当前找出的消息。
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                //这里并非else语句,因此就是否是同步屏障就直接执行到这里。
                if (msg != null) {
                    if (now < msg.when) {
                        // 下一条消息还没有准备好。设置一个超时,以便在它准备好时唤醒。也就是nextPollTimeoutMillis参数其实就是上面nativePollOnce()本地方法的参数,也就是阻塞的时长。
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        //走到这里说明找到了符合要求的Message,准备返回了。
                        mBlocked = false;
                        if (prevMsg != null) {
                            //prevMsg不为null表示当前的msg是一个异步消息,那么其值表示msg消息的上一个消息。也就是msg是从队列中间取出来的,那么就须要把队列拼接完整了。
                            prevMsg.next = msg.next;
                        } else {
                            //走到这里说明msg是一个同步消息,也是从队列的头部获取到的,那么就重置mMessages为msg的下一个消息。
                            mMessages = msg.next;
                        }
                         //清空该消息的next属性,这样该消息就是一个独立的消息。在上一步中该消息的next属性已经赋给了队列中的其它Message。
                        msg.next = null;
                        //标记正在使用
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // 没有消息就为-1.-1就表示该线程将无限期的阻塞。
                    nextPollTimeoutMillis = -1;
                }
                //处理完全部挂起的消息后,当即处理退出消息。
                if (mQuitting) {
                    dispose();
                    return null;
                }
                //。。。省略了空闲时处理IdleHandler的逻辑。IdleHandler对象,IdleHandler是一个接口,也就是继承了该接口的事物将会在MessageQueue空闲的时候去处理。GC机制就是采用的这个东西触发的。
               if (pendingIdleHandlerCount <= 0) {
                    //没有东西能够执行了,就开始等待工做。
                    mBlocked = true;
                   //continue继续执行for循环,而后在执行nativePollOnce()方法,线程阻塞。
                    continue;
                }
        }
    }
复制代码

在Looper的loop()方法中第一个重要的就是MessageQueue的next()方法。该方法有如下几点:

  1. 先开启一个For死循环,作的跟Looper的loop()方法同样。以后先阻塞线程,经过调用nativePollOnce()方法。当线程被唤起,也就是nativePollOnce()方法有返回值了,就执行后面的逻辑。
  2. 先获取当前的时间,而后跟消息的延迟时间作对比。mMessages变量表示的就是消息队列中的头布局,在MessageQueue的equeueMessage()方法中先被赋值,先是说第一此赋值的,接着在next()方法中还会被赋值。
  3. 判断Message是否是一个同步屏障,稍后解释。也就是msg.target == null,是的话就要拿出队列中第一个异步消息,也就是Message的isAsynchronous()方法返回true。若是不是同步屏障,就继续往下走。
  4. 这里再次都Message判空,是由于上一步,若是当前的消息是同步屏障的话,又找不到异步消息,那就可能返回null。
  5. 消息不为null的时候,就判断消息的延迟时间是否已经到了。若是还没到的话,就计算出剩余的事件,而后传值给nextPollTimeoutMillis变量,第1步的时候nativePollOnce()方法会用到该值,判断倒计时多久以后唤醒线程。因此该倒计时时间肯定以后,MessageQueue的next()方法中的for循环再次执行到nativePollOnce()方法的时候,就会执行该倒计时。
  6. 若是须要立马执行的话,mBlocked先变为false,也就是在MessageQueue的queueMessage()方法此时添加Message的时候就不用唤醒线程了。以后判断prevMsg是否为null,prevMsg表示了当前要执行的消息msg的前一个消息,不为null,表示msg是从队列中间位置取出来的执行的,那么这一步就得把队列继续连接起来。若是prevMsg为null,也就是说msg是从队列中的第一个位置取出的,只须要将mMessages变量从新指向msg的下一个消息就行了。
  7. 将要执行的消息msg的next属性清空,而后返回。
  8. 若是出现了同步屏障,而且下一个异步消息也没找到,那就是msg就是null 的,nextPollTimeoutMillis = -1,for循环的下次将会被阻塞住,这是个next()方法中的for死循环。
  9. 判断是否要退出。主线程是不容许被退出的。
  10. 处理那些空闲的时候才处理的IdleHandler事件,而后结束以后,mBlocked被置为true。也就是说当MessageQueue中没有任何事情可作的时候,mBlocked才是true。

上述就是MessageQueue的next()方法。通过该方法后继续看Looper的loop()方法:

//Looper.java。
public static void loop() {
        //。。。省略代码
        for (;;) {
            //。。。省略代码
            try {
                //msg.target就是Handler,而后分发消息。
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
              //。。。省略日志代码
            }
           //。。。省略日志代码
            //消息处理结束以后回收消息。
            msg.recycleUnchecked();
        }
    }
复制代码

这里获取到Message的target属性,而后调用了dispatchMessage()方法。target属性是在Handler的enqueueMessage()方法中赋值的:

//Handler.java
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
}
复制代码

也就是当前Handler对象。以后就是Handle的分发方法:

//Handler.java
public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
复制代码

代码一目了然。若是msg.callback不为null,说明当前的消息是Runnable对象。不是的话,判断mCallback是否为null,也就是Handler的构造方法中的参数Callback,不为null就调用Callback的handleMessage()方法。再接着就是调用自身的handleMessage()方法。到这Handle的源码分析就结束了!重点难点全在MessageQueue类中。

结尾:

文章可能会有理解错误的地方,但愿你们多多评论指出~
个人Github
个人掘金
个人简书
个人CSDN

相关文章
相关标签/搜索