我们都知道在onCreate方法里需要通过view.post才能获取到宽高,直接获取是获取为0的。
下面我们直接来分析下源码: View#post
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action); //1语句
}
// 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); //2语句
return true;
}
此时attachInfo==null的,这里下篇文章再讲。所以执行的语句2 继续看源码:
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++;
}
}
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);
}
}
这里会把传递过来的action封装HandleAction,然后赋值给mActions大小为4的数组存起来,那什么时候执行呢
这个runnable是在excuteActions方法里面执行的。那么这个excuteActions在哪调用呢?
也就是说当dispatchAttachedToWindow被调用时候,这个runable就执行了。
performTracelsals()这个方法是在doTravelsal里面执行的,
而mTraversalRunnable这个是在
执行的。这里加了同步屏障,这里runable可以优先执行,然后再执行我们自己view#post的那个runnable所以就能获取到宽高。
另外一种方法可以证明:我们view#post是后于performMeasure的。
mTraversalRunnable这个Runable的执行体是perforTraversals()方法,而这个方法里面执行了dispatchAttachedToWindow方法,这个方法才执行我们的view#post的runnable方法体,所以mTraversalRunnable这个runnable是驱动我们的view#post。所以就能获取到宽高。