Android View.post()方法做了过多的引用

时间:2014-08-16 12:38:27

标签: java android final conventions

抱歉,我无法提出更好的问题标题,因为它很难描述......

我正在检查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()方法中使用它。

EDIT2:

@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);
}

我仍然不明白为什么......

1 个答案:

答案 0 :(得分:1)

请记住,可以在UI线程上更新post()的同时从后台线程调用mAttachInfo。如果在mAttachInfo检查之后if (mAttachInfo != null)检查之前mAttachInfo.mHandler被设置为空,那么在Android 2.3.3之前使用的代码可能会抛出NPE。

当前代码通过拍摄mAttachInfo的快照来避免NPE,该快照在方法的生命周期内不会发生变化。

本地变量并不一定是最终的,但是声明它是最终的,这使得它更加明确,它在if (attachInfo != null)检查后不会变为空。