2021-08-08 17:08:05.156 E/MainActivity: btn: 308 168
这样简单的方法为什么可以这么方便的获取宽高呢?
先看看 View.post 的方法做了啥:
// android.view.View
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
/**
-
Causes the Runnable to be added to the message queue.
-
The runnable will be run on the user interface thread.
-
@param action The Runnable that will be executed.
-
@return Returns true if the Runnable was successfully placed in to the
-
message queue. Returns false on failure, usually because the
-
looper processing the message queue is exiting.
-
@see #postDelayed
-
@see #removeCallbacks
*/
public boolean post(Runnable action) {
// 1
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
// 2
getRunQueue().post(action);
return true;
}
}
View 的 post 方法传入了 Runnable 对象。方法注释上说:将Runnable添加到消息队列。Runnable将在用户界面线程上运行。
消息队列 message queue 不就是 Handler 机制中的 MessageQueue 吗,照这注释上的意思是传进来的 Runnable 对象最终通过 Handler 来执行到主线程。到底是不是这样,我们接着往下看。
注释 1 处 mAttachInfo 对象是 ViewRootImpl 的构造方法中创建的,然后经过层层 View 的 dispatchAttachedToWindow 方法传递给 View 的 mAttachInfo 的。当我们在生命周期 onCreate、onStart() 和 onResume() 时,ViewRootImpl 还没有被创建,所以 mAttachInfo 对象为空。一会儿梳理下 ViewRootImpl 在什么时候创建的。注释 2 处调用了 getRunQueue() 的 post 并传入 Runnable 对象
private HandlerActionQueue mRunQueue;
// android.view.View#getRunQueue()
private HandlerActionQueue getRunQueue() {
if (mRunQueue == null) {
mRunQueue = new HandlerActionQueue();
}
return mRunQueue;
}
如果 mRunQueue 对象为空,则创建,最后返回 HandlerActionQueue 类型的对象 mRunQueue。接下来看 HandlerActionQueue。
// android.view.HandlerActionQueue
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