首先来看下这些疑问:
- handler post和view post有什么区别?
- 在Activity生命周期onCreate中直接获取view的大小为0,这时通常使用view.post(runnable)方式来获取就能成功。为什么通过这种方式就可以哪?
- 在App启动速度一文中提到,为了不影响Activity启动速度,可以把一些耗时的操作通过view.post(runnable)放在第一帧绘制完成后进行。怎么确定这样就是在第一帧绘制完成后执行的哪?
handler post会把Runnable封装成Message,然后走消息机制那些流程。如果在获取view大小时通过handler post可以吗?来看下view post的实现。
源码分析
view post(runnable)
/**
* <p>Causes the Runnable to be added to the message queue.
* The runnable will be run on the user interface thread.</p>
*/
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;
}
注释可以看到这里的Runnable和Hanlder post中的一样被加入到消息队列中,并且将会在UI线程中执行。具体到代码时跟view的mAttachInfo有关:
- 不为空时,runnable会通过mHandler对象发送到UI线程的MessageQueue中,这样的话就跟普通handler post没什么区别了。(为什么是ui线程可以通过mHandler的注释得到验证)
- 为空时,将runnable放入RunQueue中。
那么post到RunQueue里的runnable什么时候执行呢,又是为何当View还没attach到window的时候,需要post到RunQueue中。
mAttachInfo 什么时候初始化的哪?RunQueue又是什么哪?
mAttachInfo的初始化
此对象的初始化在 View的dispatchAttachedToWindow()里
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
...
// 在此会执行处理RunQueue里的runnable,稍后再介绍
if (mRunQueue != null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
...
onAttachedToWindow();
}
可以看到只有当view attch到Window后,才会给mAttachInfo赋值,并且接下来会直接执行 getRunQueue().post(action) 。接下来我们看下RunQueue到底是什么以及executeActions()的实现。
RunQueue
private HandlerActionQueue getRunQueue() {