关键字View.post获取宽高
源码分析基于android-28
View.post
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
getRunQueue().post(action);
return true;
}
(1)如果attachInfo 不为空,则view绘制完成,自然是能获取宽高,attachInfo.mHandler.post这里是直接发消息给主线程;
(2)关键看 getRunQueue().post(action)的逻辑处理,我们跟进去看看;
HandlerActionQueue.post->HandlerActionQueue.postDelayed
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++;
}
}
(1)getRunQueue(),得到HandlerActionQueue类型对象;
(2)把action封装成HandlerAction放到数组里面,关键看这个数组什么时候被执行;
HandlerActionQueue.executeActions
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;
}
}
这是HandlerAction数组被执行的地方,我猜测参数handler应该是主线程的,这里的关键是看executeActions什么时候被执行;
View.dispatchAttachedToWindow
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
......
if (mRunQueue != null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
......
}
View.dispatchAttachedToWindow是执行HandlerAction数组任务的地方,那么dispatchAttachedToWindow是什么时候调用的呢?
private void performTraversals() {
final View host = mView;
......
host.dispatchAttachedToWindow(mAttachInfo, 0);
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
......
performMeasure();
......
performLayout();
......
performDraw();
......
}
ViewRootImpl.performTraversals是执行dispatchAttachedToWindow的地方,而host就是DecorView,从顶层view开始dispatchAttachedToWindow,一直到最末端的view,还有一点,mAttachInfo包含一个主线程的Handler,具体可以看它赋值的地方,这里我就不展开说了。
我们先缕下思路:ViewRootImpl.performTraversals->View.dispatchAttachedToWindow->HandlerActionQueue.executeActions->通过mAttachInfo的Handler往主线程发送消息,消息的任务是获取宽高,等待被执行,那什么时候呢,具体不知道?反正看到是在整个View树performMeasure、performLayout、performDraw执行完以后,执行完了,那自然就能获取到宽高了?为什么说一定是在这三个方法之后呢?因为android是消息驱动的,一个消息执行完才能取下一个消息,而performTraversals本身就是一个消息而且是一个异步消息,而且是在你获取宽高之前的哪个消息。
网友评论