View.Post()是怎么一回事

349 阅读1分钟

今天有点时间了,写个小知识分享。 感觉说废话浪费大家的时间,直接粘代码,相信大家能看懂的

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;
}

方法执行两条路:View被添加到窗口上了执行①,否则执行②,接下来我们分别看看①和②

final static class AttachInfo {
    ...
    final Handler mHandler;
    ...
}

如果执行了①,最终会调用Handler的post方法,至于Handler的执行流程就不在这里说了,大家可能有个疑问:mHandler从哪来的,后面写View的创建过程文章的时候会讲到,耐心等待一下

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

接下来是执行②的流程,获取了一个HandlerActionQueue对象,然后执行post->postDelayed

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;
        }
    }
    ....
}

postDelayed方法是给消息存储到mActions里面,至于这个GrowingArrayUtils.append方法是一个系统工具类,里面有数组扩容逻辑,感兴趣的可以自行查看,到此发现View.post的方法还没有执行,那我们看一下③在哪做了使用,发现只有一处使用,如下

void dispatchAttachedToWindow(AttachInfo info, int visibility) {
    ...
    if (mRunQueue != null) {
        mRunQueue.executeActions(info.mHandler);
        mRunQueue = null;
    }
    ...
}

在View被add之后会调用dispatchAttachedToWindow方法,然后调用mRunQueue.executeActions,接下来我们看看executeActions方法④,最终还是调用了AttachInfo的mHandler执行action,至此View.post的大体流程就梳理完了。

总结一下:

未命名文件.png