View.post(Runnable)
为什么可以得到 View 的真实宽高Handler.post(Runnable)
和View.post(Runnable)
有什么区别- 在
onCreate
、onResume
函数中为什么无法直接得到 View 的真实宽高View.post(Runnable)
中的 Runnable 是由谁来执行的,可以保证一定会被执行吗
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;
}
AttachInfo 是 View 的静态内部类,每个View都会持有一个AttachInfo ,它默认为null;
View中能给mAttachInfo赋值的地方只有一处,在dispatchAttachedToWindow()方法里赋值
只初始化一次: ViewRootImpl# scheduleTraversals#performTraversals#host.dispatchAttachedToWindow(mAttachInfo, 0); 事件驱动:handler同步消息~故程序执行流程和消息执行流程~在测量结束之后执行下一个消息
#存储队列 // Assume that post will succeed later
当前AttachInfo 为空是需查看#HandlerActionQueue #本地存储队列/执行任务
private HandlerActionQueue getRunQueue() {
if (mRunQueue == null) {
mRunQueue = new HandlerActionQueue();
}
return mRunQueue;
}
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++;
}
}
View中mAttachInfo是否为null?本地存储队列/执行任务
View中能给mAttachInfo赋值的地方只有一处,在dispatchAttachedToWindow()方法里赋值
只初始化一次: ViewRootImpl# scheduleTraversals#performTraversals#host.dispatchAttachedToWindow(mAttachInfo, 0); 事件驱动:handler同步消息~故程序执行流程和消息执行流程~在测量结束之后执行下一个消息
#存储队列 // Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);#7.0之前
getRunQueue().post(action);//7.0之后
#每个线程存在一个#7.0之前
static final ThreadLocal
#开启执行队列#故子线程和主线程执行post获取的不是同一个队列RunQueue getRunQueue().executeActions(mAttachInfo.mHandler);
不是不可以在子线程中调用View.post,要在View.onAttachToWindow之后在执行;
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);//View.onAttachToWindow之后在可以正常使用
}// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);//View.onAttachToWindow之前不可以子线程中调用View.post
return true;
}
每个View维护一个队列#7.0之后
private HandlerActionQueue mRunQueue; getRunQueue().executeActions(mAttachInfo.mHandler);