抱歉,我无法提出更好的问题标题,因为很难描述...
我正在检查Android的源代码(4.4 KK),尤其是View
类,结果显示为:
// .... lots of stuff....
AttachInfo mAttachInfo;
// .... lots of stuff....
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
这是我们所有人都喜欢在UI线程上需要运行某些内容时使用的
View.post(Runnable)
。我在这里不明白的是,为什么他们还要创建
attachInfo
的另一个本地引用?他们为什么不这样做:
if (mAttachInfo != null) {
return mAttachInfo.mHandler.post(action);
}
除了使
attachInfo
在方法范围内保持不变以防止错误(甚至认为它们仍然可以意外访问mAttachInfo
)之外,我认为没有任何理由这样做。另一种可能性是缩短名称,但我认为不值得缩短1个字符。
这是设计模式吗?
编辑:
进一步检查源表明,他们在许多地方都使用了这种“模式”:
public void postInvalidateOnAnimation() {
// We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
}
}
基本上,他们几乎在每个
postXXXXXX()
方法中都使用它。编辑2:
@CommonsWare指出它可能在以前的版本中用于匿名内部类,我检查了1.5(Cupcake)〜2.3.3(Gingerbread)的来源,这就是
post(
的样子public boolean post(Runnable action) {
Handler handler;
if (mAttachInfo != null) {
handler = mAttachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRoot.getRunQueue().post(action);
return true;
}
return handler.post(action);
}
我仍然不明白为什么。
最佳答案
请记住,在UI线程上更新post()
的同时,可以从后台线程调用mAttachInfo
。如果在mAttachInfo
检查之后且在访问if (mAttachInfo != null)
之前将mAttachInfo.mHandler
设置为null,直到Android 2.3.3之前使用的代码都可能引发NPE。
当前代码通过拍摄mAttachInfo
快照来避免NPE,该快照在方法的整个生命周期中都不会改变。
局部变量不一定必须是final,但是将其声明为final可以使我们更加清楚地知道,在if (attachInfo != null)
检查之后它不会变为null。