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

我正在检查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。

09-28 01:10