概述

剖析基于android12源码
Android 零碎两大外围机制 Binder机制和音讯机制
音讯零碎波及的外围类Handler、Looper、Message、MessageQueue
Android的零碎组件启动、输出、UI刷新都须要通过音讯机制来实现,某种意义上讲Android是由音讯零碎来驱动
通过传送带机制来了解

  • Message:音讯构造体携带数据和属性 <传送带上的包裹>;
  • MessageQueue:音讯队列的次要性能向音讯池投递音讯(MessageQueue.enqueueMessage)和取走音讯池的音讯(MessageQueue.next)<传送带>;
  • Handler:音讯辅助类,次要性能向音讯池发送各种音讯事件(Handler.sendMessage)和解决相应音讯事件(Handler.handleMessage)<揽件工人>;
  • Looper:一直循环执行(Looper.loop),按散发机制将音讯分发给指标解决者<传送带动力系统>。

Handler创立 - 构造函数

@Deprecatedpublic Handler() {    this(null, false);}@Deprecatedpublic Handler(@Nullable Callback callback) {    this(callback, false);}public Handler(@NonNull Looper looper) {    this(looper, null, false);}public Handler(@NonNull Looper looper, @Nullable Callback callback) {    this(looper, callback, false);}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.prepare(),能力获取Looper对象,否则为null.    mLooper = Looper.myLooper();//从以后线程绑定的ThreadLocal中获取Looper对象    if (mLooper == null) {        throw new RuntimeException(            "Can't create handler inside thread " + Thread.currentThread()                    + " that has not called Looper.prepare()");    }    mQueue = mLooper.mQueue;/音讯队列,来自Looper对象    mCallback = callback;//回调办法    mAsynchronous = async;/设置音讯是否为异步解决形式}@UnsupportedAppUsagepublic Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {    mLooper = looper;    mQueue = looper.mQueue;    mCallback = callback;    mAsynchronous = async;}@NonNullpublic static Handler createAsync(@NonNull Looper looper) {    if (looper == null) throw new NullPointerException("looper must not be null");    return new Handler(looper, null, true);}@NonNullpublic static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {    if (looper == null) throw new NullPointerException("looper must not be null");    if (callback == null) throw new NullPointerException("callback must not be null");    return new Handler(looper, callback, true);}

发送音讯相干办法

public final boolean post(@NonNull Runnable r) {   return  sendMessageDelayed(getPostMessage(r), 0);}public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {    return sendMessageAtTime(getPostMessage(r), uptimeMillis);}public final boolean postAtTime(        @NonNull Runnable r, @Nullable Object token, long uptimeMillis) {    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);}public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {    return sendMessageDelayed(getPostMessage(r), delayMillis);}/** @hide */public final boolean postDelayed(Runnable r, int what, long delayMillis) {    return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);}public final boolean postDelayed(        @NonNull Runnable r, @Nullable Object token, long delayMillis) {    return sendMessageDelayed(getPostMessage(r, token), delayMillis);}public final boolean postAtFrontOfQueue(@NonNull Runnable r) {    return sendMessageAtFrontOfQueue(getPostMessage(r));}public final boolean sendMessage(@NonNull Message msg) {    return sendMessageDelayed(msg, 0);}public final boolean sendEmptyMessage(int what){    return sendEmptyMessageDelayed(what, 0);}public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {    Message msg = Message.obtain();    msg.what = what;    return sendMessageDelayed(msg, delayMillis);}public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {    Message msg = Message.obtain();    msg.what = what;    return sendMessageAtTime(msg, uptimeMillis);}public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {    if (delayMillis < 0) {        delayMillis = 0;    }    //提早音讯,转换成相对工夫    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}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);}//下面所有的办法最终都是调这个办法 给messageQueue增加音讯private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,        long uptimeMillis) {    msg.target = this; //把以后handler本人赋给msg.target    msg.workSourceUid = ThreadLocalWorkSource.getUid();    if (mAsynchronous) {//看是否是异步音讯,进行设置        msg.setAsynchronous(true);    }    return queue.enqueueMessage(msg, uptimeMillis);//进入messageQueue的enqueueMessage}public interface Callback {    boolean handleMessage(@NonNull Message msg);}public void handleMessage(@NonNull Message msg) {}//音讯散发,回调解决public void dispatchMessage(@NonNull Message msg) {    if (msg.callback != null) {        handleCallback(msg);    } else {        if (mCallback != null) {            if (mCallback.handleMessage(msg)) {                return;            }        }        handleMessage(msg);    }}

Looper外围办法

public static void prepare() {    prepare(true);}private static void prepare(boolean quitAllowed) {    if (sThreadLocal.get() != null) { //looper是惟一的,通过Threadlocal机制实现        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}public static void loop() {    final Looper me = myLooper();//获取以后线程的Looper对象,获取失败时抛出异样    if (me == null) {        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");    }    if (me.mInLoop) {        Slog.w(TAG, "Loop again would have the queued messages be executed before this one completed.");    }    me.mInLoop = true;    Binder.clearCallingIdentity();    final long ident = Binder.clearCallingIdentity();    me.mSlowDeliveryDetected = false;    for (;;) {//开启有限循环来从音讯队列读取音讯,如果音讯队列退出了就终止循环退出        if (!loopOnce(me, ident, thresholdOverride)) {            return;        }    }} private static boolean loopOnce(final Looper me, final long ident, final int thresholdOverride) {    Message msg = me.mQueue.next(); // 获取音讯队列中的音讯对象,如果没有音讯对象就阻塞期待    if (msg == null) {        // No message indicates that the message queue is quitting.        return false;    }    ....    try {        msg.target.dispatchMessage(msg);//将音讯分发给对应的handler解决        if (observer != null) {            observer.messageDispatched(token, msg);        }        dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;    } catch (Exception exception) {        if (observer != null) {            observer.dispatchingThrewException(token, msg, exception);        }        throw exception;    } finally {        ThreadLocalWorkSource.restore(origWorkSource);        if (traceTag != 0) {            Trace.traceEnd(traceTag);        }    }    ...    //回收音讯对象,放入音讯缓存池中以待后续复用    msg.recycleUnchecked();    return true;}public static @Nullable Looper myLooper() {    return sThreadLocal.get();}public void quitSafely() {    mQueue.quit(true);}public void quit() {    mQueue.quit(false);}

MessageQueue

@UnsupportedAppUsageMessage next() {    final long ptr = mPtr;    if (ptr == 0) {//当音讯循环曾经退出,则间接返回        return null;    }    int pendingIdleHandlerCount = -1; // // 循环迭代的首次为-1    int nextPollTimeoutMillis = 0;    for (;;) {        if (nextPollTimeoutMillis != 0) {            Binder.flushPendingCommands();        }    //阻塞操作,当期待nextPollTimeoutMillis时长,或者音讯队列被唤醒,都会返回        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;            //当音讯的Handler为空时,则查问异步音讯,            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) {                if (now < msg.when) {                    // Next message is not ready.  Set a timeout to wake up when it is ready.                    //当音讯触发工夫大于以后工夫,则设置下一次轮询的超时时长                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);                } else {                    // Got a message.  获取一条音讯,并返回                    mBlocked = false;                    if (prevMsg != null) {                        prevMsg.next = msg.next;                    } else {                        mMessages = msg.next;                    }                    msg.next = null;                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);                    msg.markInUse();//设置音讯的应用状态,即flags |= FLAG_IN_USE                    return msg;//胜利地获取MessageQueue中的下一条行将要执行的音讯                }            } else {                // No more messages.  没有音讯 设置为-1 有限期待                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) {//没有idle handlers 须要运行,则循环并期待。                // 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.        //只有第一次循环时,会运行idle handlers,执行实现后,重置pendingIdleHandlerCount为0.        for (int i = 0; i < pendingIdleHandlerCount; i++) {            final IdleHandler idler = mPendingIdleHandlers[i];            mPendingIdleHandlers[i] = null; //去掉handler的援用            boolean keep = false;            try {                keep = idler.queueIdle();//idle时执行的办法            } 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.        //重置idle handler个数为0,以保障不会再次反复运行        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.        //当调用一个闲暇handler时,一个新message可能被散发,因而无需期待能够间接查问pending message.        nextPollTimeoutMillis = 0;    }}//MessageQueue是依照Message触发工夫的先后顺序排列的,队头的音讯是将要最早触发的音讯。当有音讯须要退出音讯队列时,会从队列头开始遍历,直到找到音讯应该插入的适合地位,以保障所有音讯的工夫程序。boolean enqueueMessage(Message msg, long when) {    if (msg.target == null) {// 每一个一般Message必须有一个target        throw new IllegalArgumentException("Message must have a target.");    }    synchronized (this) {        if (msg.isInUse()) {            throw new IllegalStateException(msg + " This message is already in use.");        }        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();//正在退出时,回收msg,退出到音讯回收池            return false;        }        msg.markInUse();        msg.when = when;        Message p = mMessages;        boolean needWake;        if (p == null || when == 0 || when < p.when) {            //p为null(代表MessageQueue没有音讯) 或者msg的触发工夫是队列中最早的, 则进入该该分支            msg.next = p;            mMessages = msg;            needWake = mBlocked; //当阻塞时须要唤醒        } else {            //将音讯按工夫程序插入到MessageQueue。个别地,不须要唤醒事件队列,除非            //音讯队头存在barrier,并且同时Message是队列中最早的异步音讯。            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;        }        // We can assume mPtr != 0 because mQuitting is false.        if (needWake) { //音讯没有退出,咱们认为此时mPtr != 0            nativeWake(mPtr);        }    }    return true;}//这个移除音讯的办法,采纳了两个while循环,第一个循环是从队头开始,移除符合条件的音讯,第二个循环是从头部移除完间断的满足条件的音讯之后,再从队列前面持续查问是否有满足条件的音讯须要被移除。void removeMessages(Handler h, int what, Object object) {    if (h == null) {        return;    }    synchronized (this) {        Message p = mMessages;    //从音讯队列的头部开始,移除所有符合条件的音讯        while (p != null && p.target == h && p.what == what               && (object == null || p.obj == object)) {            Message n = p.next;            mMessages = n;            p.recycleUnchecked();            p = n;        }        //移除残余的符合要求的音讯        while (p != null) {            Message n = p.next;            if (n != null) {                if (n.target == h && n.what == what                    && (object == null || n.obj == object)) {                    Message nn = n.next;                    n.recycleUnchecked();                    p.next = nn;                    continue;                }            }            p = n;        }    }}public int postSyncBarrier() {    return postSyncBarrier(SystemClock.uptimeMillis());}//插入同步屏障音讯 同步屏障音讯没有target,在音讯队列外头启动屏障作用,便于零碎的异步音讯能先失去执行private int postSyncBarrier(long when) {    // Enqueue a new sync barrier token.    // We don't need to wake the queue because the purpose of a barrier is to stall it.    synchronized (this) {        final int token = mNextBarrierToken++;        final Message msg = Message.obtain();        msg.markInUse();        msg.when = when;        msg.arg1 = token;        Message prev = null;        Message p = mMessages;        if (when != 0) {            while (p != null && p.when <= when) {                prev = p;                p = p.next;            }        }        if (prev != null) { // invariant: p == prev.next            msg.next = p;            prev.next = msg;        } else {            msg.next = p;            mMessages = msg;        }        return token;    }}public void removeSyncBarrier(int token) {    // Remove a sync barrier token from the queue.    // If the queue is no longer stalled by a barrier then wake it.    synchronized (this) {        Message prev = null;        Message p = mMessages;        //从音讯队列找到 target为空,并且token相等的Message        while (p != null && (p.target != null || p.arg1 != token)) {            prev = p;            p = p.next;        }        if (p == null) {            throw new IllegalStateException("The specified message queue synchronization "                    + " barrier token has not been posted or has already been removed.");        }        final boolean needWake;        if (prev != null) {            prev.next = p.next;            needWake = false;        } else {            mMessages = p.next;            needWake = mMessages == null || mMessages.target != null;        }        p.recycleUnchecked();        // If the loop is quitting then it is already awake.        // We can assume mPtr != 0 when mQuitting is false.        if (needWake && !mQuitting) {            nativeWake(mPtr);        }    }}void quit(boolean safe) {    if (!mQuitAllowed) {// 当mQuitAllowed为false,示意不运行退出,强行调用quit()会抛出异样        throw new IllegalStateException("Main thread not allowed to quit.");    }    synchronized (this) {        if (mQuitting) {//避免屡次执行退出操作            return;        }        mQuitting = true;        if (safe) {            removeAllFutureMessagesLocked();//移除尚未触发的所有音讯        } else {            removeAllMessagesLocked();//移除所有的音讯        }        //mQuitting=false,那么认定为 mPtr != 0        nativeWake(mPtr);    }}

Message

//享元模式 防止频繁创立和销毁对象造成gcpublic static Message obtain() {    synchronized (sPoolSync) {        if (sPool != null) {            Message m = sPool;            sPool = m.next;            m.next = null;//从sPool中取出一个Message对象,并音讯链表断开            m.flags = 0; // 革除in-use flag            sPoolSize--;//音讯池的可用大小进行减1操作            return m;        }    }    return new Message();// 当音讯池为空时,间接创立Message对象}public void recycle() {    if (isInUse()) {//判断音讯是否正在应用        if (gCheckRecycle) {            throw new IllegalStateException("This message cannot be recycled because it "                    + "is still in use.");        }        return;    }    recycleUnchecked();}/** * Recycles a Message that may be in-use. * Used internally by the MessageQueue and Looper when disposing of queued Messages. */@UnsupportedAppUsagevoid recycleUnchecked() {    // Mark the message as in use while it remains in the recycled object pool.    // Clear out all other details.    flags = FLAG_IN_USE;//将音讯标示地位为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;    synchronized (sPoolSync) {        if (sPoolSize < MAX_POOL_SIZE) {//当音讯池没有满时,将Message对象退出音讯池            next = sPool;            sPool = this;            sPoolSize++;//音讯池的可用大小进行加1操作        }    }}

总结思考

  1. handler发送提早音讯是如何解决的,第一次发送提早20秒的音讯,第二次发送提早10秒的音讯,如何保障第二次的音讯优先执行的
  2. 屏障音讯的作用,什么状况下须要音讯屏障和异步音讯
  3. 创立音讯为什么要用obtain()
  4. 音讯队列没有音讯的时候是如何实现阻塞的