我是苍王,以下是我这个系列的相关文章,有兴趣可以参考一下,可以给个喜欢或者关注我的文章。
[Android]如何做一个崩溃率少于千分之三噶应用app--章节列表
有一定开发经验,大家应该对Handler的机制有非常深刻的了解,Handler在Android开发中被广泛用于线程间通信。
近来遇到了一个问题,在view init的情况下使用view自身的handler会崩溃,但是直接使用postDelay却能正常运行。
这里需要思考几个问题
1.view的handler是从哪里来的呢?
2.view的handler为何会崩溃?
3.View的post的运行机制是?
读了这篇文章,你就能理解到这些问题
1.view的handler是从哪里来的呢?
public Handler getHandler() {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler;
}
return null;
}
可以看到是handler是从mAttachInfo过来的.
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
……
在dispatchAttachedToWindow的时候来传递过来,而viewgroup中触发这个传递操作。
这里最终会在ViewRootImpl中创建出来AttachInfo对象。
而handler是来自于自定义的ViewRootHandler,那就可以知道,整个Activity的View系统共用一个Handler是由ViewRootImpl创建,用于处理页面视图事件等处理。
2.view的handler为何会崩溃?
dispatchAttachedToWindow是在View调用init初始化之后的,handler还没有被初始化,所以就导致handler返回null对象出外,如果不判空就会崩溃了。
3.View的post的运行机制是?
可以看到当mAttachInfo未初始化的时候,会先将runnable塞到一个队列当中。
public boolean postDelayed(Runnable action, long delayMillis) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.postDelayed(action, delayMillis);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().postDelayed(action, delayMillis);
return true;
}
当view被绑定到窗口的时候,会将队列和handler绑定,然后启动队列任务
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
……
// Transfer all pending runnables.
if (mRunQueue != null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
……
}
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.postDelayed(handlerAction.action, handlerAction.delay);
}
mActions = null;
mCount = 0;
}
}