view.post()什么情况下使用
- 通过view.post可以获取元素的高度和宽度
为什么可以获取到测量后的高度
- view.post 在callback的时候说明是已经完成view的measure,Layout, draw
- 开始我们最喜欢的源码跟进环节
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