View中的Post实现如下:

public boolean post(Runnable action) {
    final AttachInfo attachInfo = mAttachInfo;
    if (attachInfo != null) {
        return attachInfo.mHandler.post(action);
    }

    // Postpone the runnable until we know on which thread it needs to run.
    // Assume that the runnable will be successfully placed after attach.
    getRunQueue().post(action);
    return true;
}

这个实现主要分为两种情况,第一种就是mAttachInfo有值的情况下,一种是没有。

有值的情况下很简单,就是调用了它内部的mHandler对象,它是一个Hanlder对象,这样这个runnable会被直接执行。

@UnsupportedAppUsage
final Handler mHandler;

mAttachInfo没有值情况下

会调用getRunQueue方法,如下:

private HandlerActionQueue getRunQueue() {
    if (mRunQueue == null) {
        mRunQueue = new HandlerActionQueue();
    }
    return mRunQueue;
}

它创建了一个叫做HandlerActionQueue的对象,来看下这个类的核心实现,如下:

public class HandlerActionQueue {
    private HandlerAction[] mActions;
    private int mCount;

    public void post(Runnable action) {
        postDelayed(action, 0);
    }
    
    public void postDelayed(Runnable action, long delayMillis) {
        final HandlerAction handlerAction = new HandlerAction(action, delayMillis);

        synchronized (this) {
            if (mActions == null) {
                mActions = new HandlerAction[4];
            }
            mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
            mCount++;
        }
    }
    
    public void executeActions(Handler handler) {
        synchronized (this) {
            final HandlerAction[] actions = mActions;
            for (int i = 0, count = mCount; i < count; i++) {
                final HandlerAction handlerAction = actions[i];
                handler.postDelayed(handlerAction.action, handlerAction.delay);
            }

            mActions = null;
            mCount = 0;
        }
    }
    private static class HandlerAction {
        final Runnable action;
        final long delay;

        public HandlerAction(Runnable action, long delay) {
            this.action = action;
            this.delay = delay;
        }

        public boolean matches(Runnable otherAction) {
            return otherAction == null && action == null
                    || action != null && action.equals(otherAction);
        }
    }
}

这个类的post就是刚才getRunQueue().post(action)调用的,然后它内部是调用了自己的postDelayed方法,这个方法把传过来的Runnable又包装了一层成了HandlerAction,然后存到数组中。然后就没了。

那我的Runnable啥时候执行的?它提供了executeActions函数用于执行所有的HandlerAction,也就是封装了我们Runnable对象的对象,这个方法在View的dispatchAttachedToWindow方法中被调用,如下:

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        mAttachInfo = info;
		//... ...
        // Transfer all pending runnables.
        if (mRunQueue != null) {
            mRunQueue.executeActions(info.mHandler);
            mRunQueue = null;
        }
        //... ...
    }

这时mAttachInfo就有值了,然后就是调用了executeActions方法,把存下来的Runnable全部执行。dispatchAttachedToWindow之后的所有view.post都会直接通过mHandler执行,无需等待。因为mAttachInfo已经有值了。

public boolean post(Runnable action) {
    final AttachInfo attachInfo = mAttachInfo;
    if (attachInfo != null) {
        return attachInfo.mHandler.post(action);
    }

    // Postpone the runnable until we know on which thread it needs to run.
    // Assume that the runnable will be successfully placed after attach.
    getRunQueue().post(action);
    return true;
}

流程如下:

image-20200716131117464