【问题标题】:DialogFragment getActivity() "might be null" lint warning in AndroidStudio 3.0.1AndroidStudio 3.0.1 中的 DialogFragment getActivity()“可能为空”lint 警告
【发布时间】:2018-06-08 06:19:15
【问题描述】:

我能找到的最接近的现有问题是Android Studio 3.0 lint warnings for references to activity,但它没有帮助。

使用 AndroidStudio 3.0.1,我有一个 DialogFragment,我在其中做这些通常的事情:

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

Argument 'getActivity()' might be null 我有一个棉绒警告在抱怨我。

我了解 为什么 getActivity() 可能为空,并且我了解 lint 检查如何知道这一点(来自 @Nullable 注释)。

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

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

【问题讨论】:

  • “我该如何解决不整洁的 lint 警告?” -- 压制它并继续前进。
  • 为什么不用getContext()
  • 也许您可以依靠 onActivityCreated 或 onAttach(已弃用),这将为您提供有效的参考。然后用它代替 getActivity() ?
  • @CommonsWare 是你推荐的 @SuppressWarnings("ConstantConditions") 吗?
  • 如果这是快速修复所建议的,并且有效,那么是的。或者,如果您发现注释比突出显示的代码段更烦人,请在精神上抑制它。或者,将null 签入并在实际为null 的情况下抛出IllegalStateException(这不应该发生)。

标签: java android lint


【解决方案1】:

对于那些想查看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; 
     }
 } 

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      如果他们将返回值注释为@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,如果发生这种情况,应用程序崩溃是可以的。这就是为什么我说我更愿意在支持库代码中使用它。

      编辑:

      添加了一种新方法来支持 Fragments - requireActivity()。这个方法等价于上面描述的getActivityNonNull()(虽然如果没有附加到Activity,它会抛出IllegalStateException)。

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

      【讨论】:

      • 该方法于2018年2月添加-version 27.1.0
      • 完美!我通常也不喜欢抑制或忽略 lints。感谢最近的添加。下面是相同的源代码块。 @NonNull public final FragmentActivity requireActivity() { FragmentActivity 活动 = this.getActivity(); if (activity == null) { throw new IllegalStateException("Fragment " + this + " 未附加到活动。"); } else { 返回活动; } }
      • 所以,使用这个最近添加的方法 requireActivity(),我们不会得到 NPE,但会得到 RuntimeException,这等同于相同的行为......你去谷歌!
      【解决方案4】:

      这是 - Android Studio 3.0 lint warnings for references to activity 的副本。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-31
        • 2013-04-08
        • 1970-01-01
        • 2014-08-23
        • 2010-11-11
        • 1970-01-01
        相关资源
        最近更新 更多