我在尝试在片段中显示吐司的一些设备上出现错误。 这种吐司通常是在翻新响应失败时进行的。 吐司代码很简单。 请提出建议,找不到在这里和那里搜索的任何原因。
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)
使用getContext()而不是getActivity()
嗨,Syed丹麦人Haider。 谢谢您的回答。。。请您为我的建议提供一些解释,以帮助我理解。
我已经为您的答辩贴出了答案,如果有帮助请接受我的答案
将应用程序上下文保存在全局变量中,并使用该全局变量代替getActivity()
@Kushal我喜欢-我们必须在思考。 我是在您发布此消息的同时将其添加到我的答案中的。 我还提供了指向代码的链接,该代码使用Singleton模式完成。 可能并非在所有情况下都是最好的,但是对于像这样的棘手情况,这是一个不错的解决方法。
根据Fragment.getActivity()的代码和javadoc,您可以返回null:
/**
* 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。
关于这些帖子何时可以为null的讨论很好:
为什么片段中的getContext()有时会返回null?
已经提供了简单的解决方案-在显示Toast之前放入null检查。
但是潜在的问题是体系结构之一-您的代码将API活动耦合到您的UI,并假设有关UI状态的某些事情,即您假设当API调用返回时,用户仍然可以看到屏幕。
更好的解决方案是将Retrofit调用与UI分离-将API调用放在不依赖于UI状态的单独的类中。
使用事件或pub-sub框架从此API包装器类传递回任何需要知道API调用何时返回的UI组件。
EventBus或RxJava是这方面的2种常见解决方案(LocalBroadcastManager是一种不太常见的方法)。
这将允许任何代码调用您的API,并在API返回时订阅通知。
它还允许您将API响应保存在(例如)本地数据库中,在这种情况下,您可以仅依靠LiveData模式来更新所需的任何UI。
这是一篇中型文章,简要介绍了如何使用Repository模式以这种方式使用Android体系结构组件。
由于某些项目无法立即重新设计,因此可能需要解决方法。
上面提到的null检查解决方法很有用,因为该应用程序将不再崩溃。不幸的是,这确实意味着不会通知用户有关失败的API调用的信息。
一种替代方法是创建您自己的Application子类(许多项目已经完成此操作以初始化公共库),并提供了一种静态访问此应用程序context的方法。 (库舒尔随后提出了类似的建议。)
然后,您可以选择使用应用程序context而不是片段中的那个来显示Toast。您可能会丢失从更特定的上下文中获得的任何特定样式,但是这样做的好处是您的用户仍然可以看到Toast消息。
这篇文章很好地描述了将Application暴露为单例。
Android中应用程序单例的使用
感谢您的详细解释。 我可以说明崩溃/ ANR读取它的原因。 到目前为止,可能无法进行体系结构更改。 我会将此与您对未来计划的建议一起保留。
100%理解困难或重新整理现有代码,这就是为什么我专门链接到其他答案-我有很多代码可以进行简单的if(x != null){}检查-但似乎普遍误解为getActivity() / getContext() 总是可用的,所以我认为对此类问题的详细回答可能对将来的读者有用。
@BharatKumar Ive添加了另一个解决方法,因此您仍然可以通过使用应用程序上下文向用户显示Toast-这可能比根本不显示任何内容有用。
片段分离时也许调用了getActivity()。试试吧。
if (isAdded()) {
Toast.makeText(getActivity(),"something", Toast.LENGTH_SHORT).show();
}
当片段未与Activity关联时,有时getActivity()或getContext()可能会产生空指针异常。因此,使用onAttach方法
public class yourFragment extends Fragment {
Context context
@Override
public void onAttach(Context context) {
this.context = context;
super.onAttach(context);
}
}
您的活动context在此行中为null:
Toast.makeText(getActivity(),"Connection Failure", Toast.LENGTH_LONG).show();// getActivity() is null
为了避免崩溃,请使用以下命令:
if(getActivity() != null)
Toast.makeText(getActivity(),"Connection Failure", Toast.LENGTH_LONG).show();
if (isAdded()) {
Toast.makeText(getActivity(),"something", Toast.LENGTH_SHORT).show();
}
或尝试这个
if(getActivity() != null)
Toast.makeText(getActivity(),"Connection Failure", Toast.LENGTH_LONG).show();
在我的情况下,两者都可以正常工作,因为在某些情况下,在片段分离时调用getActivity()。
因此,我们也必须注意这一点。
将您的getActivity()更改为getContext()。请尝试以下给定的代码:
Toast.makeText(getContext(),"Connection Failure", Toast.LENGTH_LONG).show();
请注意,getContext()也可以返回null