View.post()到底做什么

view.post()什么情况下使用

  1. 通过view.post可以获取元素的高度和宽度

为什么可以获取到测量后的高度

  1. view.post 在callback的时候说明是已经完成view的measure,Layout, draw
  2. 开始我们最喜欢的源码跟进环节
    public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        // 1. 先说结论,当已经view已经attatch,调用attach的handler,执行post
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
        
        //2. 如果没有的话,比如我们在oncreate方法里调用view.post,这个时候就是没有
        然后就会被缓存起来,知道attach后开始调用
        getRunQueue().post(action);
        return true;
    }

先从第一种情况说起。 view是何时attach的,看一下attachInfo是何时赋值的

void dispatchAttachedToWindow(AttachInfo info){
    mAttachInfo = info
    
    // 执行所有的[真正开始进入队列的地方]
    if (mRunQueue != null) {
            // 在dispatchToWindow的时候执行所有的缓存的task
            mRunQueue.executeActions(info.mHandler);
            mRunQueue = null;
    }
}

继而继续跟进View.java##dispatchAttachedToWindow() 何时调用的, 首先ViewGroup中肯定会调用到。 果然
ViewGroup.java

 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        mGroupFlags |= FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW;
        // 先完成自身的dispatch,这里对于ViewTree是按照深度优先先序遍历
        super.dispatchAttachedToWindow(info, visibility);
        mGroupFlags &= ~FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW;

        final int count = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < count; i++) {
            final View child = children[i];
            // 循环调用子View的
            child.dispatchAttachedToWindow(info,
                    combineVisibility(visibility, child.getVisibility()));
        }
    }

接着肯定是在根view DecorView中看有没调用,确认没有后。去管理view的 绘制以及事件的类ViewRootImpl.java中去看看, 果然在这里调用了。

private void performTraversals(){
    // 这里的mView,就是DecorView
    final View host = mView;
    if(mFirst){
         host.dispatchAttachedToWindow(mAttachInfo, 0);
    }
    
    // 测量
    performMesaure();
    
    // 布局
    performLayout();
    
    // 绘制
    performDraw();
}

于是结合[真正开始进入队列的地方] 这个地方,问题就来,这个明明是在view绘制之前调用的嘛,这样不是取值为0吗,
这个地方又要回到之前在“再读源码值消息机制里”里的消息屏障了。这里所有的绘制消息会优先执行,然后再执行 post的这个target

你可能感兴趣的:(View.post()到底做什么)