view.post()
使用场景
有时候使用view.getWidth()返回是0,因为这时候view还没被绘制出来。使用view.post(new Runnble)可以在view绘制完成后,在runnable里面获得view的宽高。
原理
public boolean post(Runnable action) {
// ...
// 判断AttachInfo是否为null
final AttachInfo attachInfo = mAttachInfo;
// 若不为null,直接调用其内部Handler的post ->>
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// 若为null,则加入当前View的等待队列
getRunQueue().post(action);
return true;
}
AttachInfo在view.dispatchAttachedToWindow()方法中被赋值,所以在Activity的onCreate()方法中,AttachInfo为空,只是把runnable添加到view的队列中。
public void postDelayed(Runnable action, long delayMillis) {
// 将传入的任务runnable封装成HandlerAction
final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
synchronized (this) {
// 将要执行的HandlerAction 保存在 mActions 数组中
if (mActions == null) {
mActions = new HandlerAction[4];
}
mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
mCount++;
}
}
把runnable封装成HandlerAction ,并且保存在mActions 数组中,当
public void executeActions(Handler handler) {
synchronized (this) {
final HandlerAction[] actions = mActions;
// 遍历所有任务
for (int i = 0, count = mCount; i < count; i++) {
final HandlerAction handlerAction = actions[i];
// 发送到Handler中,等待执行
handler.postDelayed(handlerAction.action, handlerAction.delay);
}
// 此时不再需要后续的post,将被添加到AttachInfo中
mActions = null;
mCount = 0;
}
当view绘制完成后,遍历所有的任务,执行任务
View.post() 添加的任务能够保证在所有 View绘制流程结束之后才被执行,所以 执行View.post() 添加的任务时可以正确获取到 View 的宽高。
网友评论