我在尝试在片段中显示祝酒词的少数设备上遇到错误。这种祝酒词通常针对改装响应失败。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)
根据规范
/**
* 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。
在这篇可能相关的帖子中,有一个关于这些何时可以为空的很好的讨论:
已经提供了一个简单的解决方案——在显示<code>Toast</code>之前进行空检查。
但潜在的问题是架构问题——你的代码将API活动耦合到你的UI,并假设关于你的UI状态的某些事情,即你假设当API调用返回时,你的屏幕仍然对用户可见。
更好的解决方案是将改造调用与 UI 分离 - 将 API 调用放在不依赖于 UI 状态的单独类中。
使用事件或pub-sub框架从这个API包装类通信回任何需要知道API调用何时返回的UI组件。
EventBus
或 RxJava
是 2 个常见的解决方案(LocalBroadcastManager
是一种不太常见的方法)。
这将允许任何代码调用您的API,并在API返回时订阅通知。
它还允许您将API响应保存在(例如)本地数据库中,在这种情况下,您可以仅依靠LiveData
模式来更新任何需要的UI。
这里有一篇Medium文章,简要描述了如何使用Repository
模式以这种方式使用Android架构组件。
考虑到一些项目不能立即重新设计,可能需要变通方法。
上面提到的空值检查解决方法非常有用,因为应用程序将不再崩溃。不幸的是,这意味着用户不会被警告API调用失败。
一种替代方法是创建您自己的Application
子类(许多项目已经这样做了,以便初始化公共库),并提供对该应用程序Context
的静态访问方法。(Kushal随后提出了类似的建议。)
然后,您可以选择使用应用程序Context
而不是片段中的那个来显示Toast
。您可能会丢失从更具体的上下文中获得的任何特定样式,但优点是您的用户仍然可以看到Toast
消息。
将您的Application
暴露为单例在这篇文章中得到了很好的描述:
有时,当片段与“活动”不关联时,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();
}