DialogFragment getActivity() "might be null" AndroidStudio 3.0.1 中的 lint 警告

DialogFragment getActivity() "might be null" lint warning in AndroidStudio 3.0.1

我能找到的与此最接近的现有问题是 ,但它没有帮助。

使用 AndroidStudio 3.0.1,我有一个 DialogFragment 可以执行以下常规操作的地方:

    @Override
    @NonNull
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        ...

我有一个 lint 警告在向我抱怨 Argument 'getActivity()' might be null

我明白 为什么 getActivity() 可能为空,我明白 lint 检查是如何知道这一点的(来自 @Nullable 注释)。

我的问题是:getActivity() 可能为空这一切都很好,但实际上我应该如何优雅而整洁地处理这个问题? onCreateDialog 必须 return一个Dialog(因为超类'@Nullable注释)所以我必须 有 Activity 上下文来创建它。

如果 DialogFragment 没有附加到 Activity,我可以假设 onCreateDialog 永远不会被调用,但仍然 - 我如何解决不整洁的 lint 警告?

这是 - 的副本。

tldr; getActivity() 获得了支持 lib 27.0.0 注释 @Nullable 并且静态分析工具现在可以使用它。

@Niklas 的回答解释了您现在收到此警告的原因。我想分享我对你实际应该做什么的想法。

首先,所有这些添加的可空性所做的就是暴露这些年来一直存在的旧设计缺陷 - 这种方法总是 return null(例如片段分离)。

我希望他们将 return 值注释为 @NonNull 并在 Activity 实际上为 null 时调用此方法时在内部抛出异常,但我知道这会破坏向后兼容性因此风险很大(尽管我几乎不明白为什么有人会在 Activity 实际上可以为 null 时调用此方法)。

那么,我们应该怎么办呢?

首先,由于功能根本没有改变,如果有问题的代码已经工作,那么按照@CommonsWare 的建议进行操作 - 抑制警告或忽略它。

您还可以将每个调用包装到空检查中,例如异常。

但是,我要做的是将此方法放入我的 BaseDialog(由所有其他对话框扩展):

protected FragmentActivity getActivityNonNull() {
    if (super.getActivity() != null) {
        return super.getActivity();
    } else {
        throw new RuntimeException("null returned from getActivity()");
    }
}

请注意,所有这些选项都有效地表明您并不真正期望 null 被 returned 并且如果发生这种情况应用程序崩溃是可以接受的。这就是为什么我说我更愿意在支持库代码中使用它。

编辑:

添加了一种新方法来支持片段 - requireActivity()。此方法等效于上面描述的 getActivityNonNull()(尽管如果未附加到 Activity,它会抛出 IllegalStateException)。

用这个方法代替getActivity(),你应该会很好。

这些方法是在修订版 27.1.0 中添加的 Release:Fragments 现在有 requireContext()requireActivity()requireHost()requireFragmentManager() 方法,其中 return 等效 get 方法的 NonNull 对象或抛出 IllegalStateException。

对于那些想要查看 requireActivity() 方法源代码的人:

 @NonNull 
 public final FragmentActivity requireActivity() { 
     FragmentActivity activity = this.getActivity();
     if (activity == null) { 
         throw new IllegalStateException(
             "Fragment " + this + " not attached to an activity."
         );
     } else {
         return activity; 
     }
 }