为什么View.post 方法一定能拿到控件的宽高

众所周知,当我们开发时,如果在在View没有测量完毕就拿不到宽高,比如在Activity.onCreate方法中获取View的宽高是拿不到的,这是为什么呢?

View.post.png
  • View.post方法调用时,如果在 View 还没开始绘制时( Activity 的 onResume方法还没回调之前 或者onResume方法执行了,但是 ViewRootImpl 的 performTraversals 还没开始执行)就会用一个初始长度为 4 的数组缓存起来(Runnable 数量大于4时会进行扩容),ViewRootImpl 在初始化时创建了一个 View.AttchInfo 对象并绑定 ViewRootImpl 的 Handler ,该 Handler 也用于发送 View 绘制相关的 msg ;

  • 等到 ViewRootImpl执行 performTraversals方法时(此时 Activity 已经回调了onResume),会配置 View 的 AttchInfo 对象并且通过 View 的 dispatchAttachedToWindow 方法传入到 View 里面完成绑定,在该方法中会取出 View 缓存的 Runnable 并用 View.AttchInfo 的 Handler 来进行 post 方法,这样子就会加入到 MessageQueue 里面进行排队,等到这些缓存 Runnable 执行时,主线程里面 View的绘制流程也就结束了,所以这时候 Looper 取出这些缓存的Runnable 执行时就可以拿到 View 的宽高。

  • 那么,什么情况下View.post 方法不会执行呢?如果 Activity 因为某些原因没有执行到 onResume 的话,无法顺利调用 ViewRootImpl 的 performTraversals 的话,View.post 方法就不会执行

  • 如果 View 是 new 出来的,并且没有通过 addView 等方法依赖到 DecorView 上面,它的 post 方法也是不会执行的,因为它没有机会和 ViewRootImpl 进行互动了

  • 其中,View.post的Handler和ViewRootImpl中的Handler(ViewRootHandler)是一样的

你可能感兴趣的:(为什么View.post 方法一定能拿到控件的宽高)