View的post(Runnable),Runnable的run为什么可以用来获取View的宽高?
先看post方法源码,很短:
public boolean post(Runnable action) {
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.
getRunQueue().post(action);
return true;
}
1.先看AttachInfo是什么,只看注释:
/**
* A set of information given to a view when it is attached to its parent
* window.
*/
final static class AttachInfo {
interface Callbacks {
void playSoundEffect(int effectId);
boolean performHapticFeedback(int effectId, boolean always);
}
说的很明白,当view添加到父视图时给view的一系列信息。
2.所以,再看post方法, if (attachInfo != null)说明已经添加到父视图了,已经初始化好了,这时候将Runnable投递到相应消息队列执行的时候,因为view已经初始化好,所以能获取到宽高。
3.还是post方法,如果,attachInfo 等于null,那么 getRunQueue().post(action);看一下
/**
* Class used to enqueue pending work from Views when no Handler is attached.
*
* @hide Exposed for test framework only.
*/
public class HandlerActionQueue {
private HandlerAction[] mActions;
private int mCount;
public void post(Runnable action) {
postDelayed(action, 0);
}
注释中,说明是在view未添加到父视图时对Runnable的排队处理,同时,在View的
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
//...
// Transfer all pending runnables.
if (mRunQueue != null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
中可以看到,在被添加的时候,会再次取出排队的Runnable执行。言下之意,view在没有初始化的时候,会将受到的Runnable保存下来,当初始化成功后再取出来执行,所以也能获取到正确的宽高。
网友评论