提问者:小点点

显示空指针 expn 的 Android 片段中的 Toast


我在尝试在片段中显示祝酒词的少数设备上遇到错误。这种祝酒词通常针对改装响应失败。toast代码很简单。请建议,找不到任何原因在这里和那里搜索。

Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();

我的 ST 日志在下面。

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
   at android.widget.Toast.(Toast.java:103)
   at android.widget.Toast.makeText(Toast.java:256)

共3个答案

匿名用户

根据规范

/**
 * Return the {@link FragmentActivity} this fragment is currently associated with.
 * May return {@code null} if the fragment is associated with a {@link Context}
 * instead.
 *
 * @see #requireActivity()
 */
@Nullable
final public FragmentActivity getActivity() {
    return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}

特别是当您的片段未附加到活动时,可能会发生这种情况(如此处和此处所述)。

类似地,getContext()也可以返回null。

在这篇可能相关的帖子中,有一个关于这些何时可以为空的很好的讨论:

    < li >为什么fragment中的getContext()有时会返回null?

已经提供了一个简单的解决方案——在显示<code>Toast</code>之前进行空检查。

但潜在的问题是架构问题——你的代码将API活动耦合到你的UI,并假设关于你的UI状态的某些事情,即你假设当API调用返回时,你的屏幕仍然对用户可见。

更好的解决方案是将改造调用与 UI 分离 - 将 API 调用放在不依赖于 UI 状态的单独类中。

使用事件或pub-sub框架从这个API包装类通信回任何需要知道API调用何时返回的UI组件。

EventBusRxJava 是 2 个常见的解决方案(LocalBroadcastManager 是一种不太常见的方法)。

这将允许任何代码调用您的API,并在API返回时订阅通知。

它还允许您将API响应保存在(例如)本地数据库中,在这种情况下,您可以仅依靠LiveData模式来更新任何需要的UI。

这里有一篇Medium文章,简要描述了如何使用Repository模式以这种方式使用Android架构组件。

考虑到一些项目不能立即重新设计,可能需要变通方法。

上面提到的空值检查解决方法非常有用,因为应用程序将不再崩溃。不幸的是,这意味着用户不会被警告API调用失败。

一种替代方法是创建您自己的Application子类(许多项目已经这样做了,以便初始化公共库),并提供对该应用程序Context的静态访问方法。(Kushal随后提出了类似的建议。)

然后,您可以选择使用应用程序Context而不是片段中的那个来显示Toast。您可能会丢失从更具体的上下文中获得的任何特定样式,但优点是您的用户仍然可以看到Toast消息。

将您的Application暴露为单例在这篇文章中得到了很好的描述:

  • 在Android系统中使用应用程序单例

匿名用户

有时,当片段与“活动”不关联时,getActivity()或getContext()可能会产生空指针异常。所以使用onAttach方法

public class yourFragment extends Fragment {
   Context context

   @Override
   public void onAttach(Context context) {
        this.context = context;
        super.onAttach(context);
   }
}

匿名用户

可能在片段分离时调用了< code>getActivity()。试试看。

if (isAdded()) {
    Toast.makeText(getActivity(), "something", Toast.LENGTH_SHORT).show();
}