片段:getContext 与 requireContext

2025-06-09

片段:getContext 与 requireContext

TLDR:仅当您确定片段已附加到其主机(onResume、onViewCreated 等)时才使用 requireContext。

问题

getContext 与 requireContext

Android 团队在 27.1.0 版的支持库中为一些 SDK 方法添加了 NonNull 和 Nullable 注释。这一更改会导致出现如上图所示的警告和错误。

他们为什么这么做?

乍一看,这似乎给 Android 应用开发带来了越来越多的麻烦。但实际上,这些注解有助于我们降低崩溃率。

当 fragment 未附加到其主机时,getContext 可能会返回 null。我们来看两个例子。

@Override
public void onResume() {
    super.onResume();
    Resources resources = getContext().getResources();
}
Enter fullscreen mode Exit fullscreen mode

第一个示例向我们展示了,只要片段附加到其主机(例如在 onResume 中),就可以安全地使用 getContext 而无需进行可空性检查。

@Override
public void onResume() {
    super.onResume();
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            final Resources resources = getContext().getResources();
        }
    }, TimeUnit.SECONDS.toMillis(5));
}
Enter fullscreen mode Exit fullscreen mode

第二个漏洞揭示了潜在的 NullPointerException。如果 5 秒后 fragment 仍未连接到主机,应用程序就会崩溃。

因此,getContext Nullable 注解可以避免像第二个示例中那样的错误。但它会在 Java 中的第一个示例中引发无用的警告,并在 Kotlin 中引发错误。

我们应该如何解决这个问题?

首先我们应该修复潜在的错误。

  1. 找到在某个时间点可以分离片段的所有位置
  2. 按照下面的示例更改代码

在 Java 中:

Context context = getContext();
if (context == null) {
    // Handle null context scenario
} else {
    // Old code with context
}

Enter fullscreen mode Exit fullscreen mode

在 Kotlin 中:

val context: Context = this.context ?: return // or if block
Enter fullscreen mode Exit fullscreen mode

最后,用 requireContext() 替换其余部分,它会返回非空上下文,而不是 getContext()。但请记住,如果 fragment 未连接到其宿主,requireContext() 会抛出异常。因此,您应该根据 fragment 的生命周期使用 requireContext()。

错误修复

在 Java 中:

1.
// requireContext() does the same
Context context = getContext();
if (context == null) {
    throw new IllegalStateException("");
}

2.
// Warning supressing only hides the real problem
private void doSomething(@NonNull final Context context) {
}

@Override
public void onResume() {
    super.onResume();

    //noinspection ConstantConditions
    doSomething(getContext());
}
Enter fullscreen mode Exit fullscreen mode

在 Kotlin 中:

// It is similar to requireContext() but with NullPointerException
val context: Context = context!!
Enter fullscreen mode Exit fullscreen mode

其他类似方法

  1. getActivity 与 requireActivity
  2. getHost 与 requireHost
  3. getFragmentManager 与 requireFragmentManager
鏂囩珷鏉ユ簮锛�https://dev.to/ivanshafran/fragment-getcontext-vs-requirecontext-4149
PREV
用 GraphQL 还是不用?优点和缺点
NEXT
Android 单元测试的演变 零版本:没有单元测试 第一个版本:我的第一个单元测试 学习一些关于 JUnit 框架的知识 从业务逻辑中抽象出 Android Mocks 第一个单元测试 第二个版本:代码清理 第三个版本:模拟库 第四个版本:Kotlin 第五个版本:Spek 奖励部分