Android 片段中的 Toast 显示空指针 expn
Toast in Android fragments showing null pointer expn
我尝试在片段中显示吐司时,在少数设备上遇到错误。这个吐司通常是在改造响应失败时。 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)
你的activitycontext
在这行是空的:
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();// getActivity() is null
为避免崩溃,请使用:
if(getActivity() != null)
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();
有时,当片段未与 Activity 相关联时,getActivity() 或 getContext() 可能会产生空指针异常。所以使用onAttach方法
public class yourFragment extends Fragment {
Context context
@Override
public void onAttach(Context context) {
this.context = context;
super.onAttach(context);
}
}
将您的 getActivity()
更改为 getContext()
。试试下面给定的代码:
Toast.makeText(getContext(), "Connection Failure", Toast.LENGTH_LONG).show();
可能 getActivity()
在片段分离时调用。试试吧。
if (isAdded()) {
Toast.makeText(getActivity(), "something", Toast.LENGTH_SHORT).show();
}
根据 Fragment.getActivity()
的代码和 javadoc,您可以得到 null
returned:
/**
* 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();
}
尤其是当您的 Fragment 未附加到 activity 时(如 and 所指出的),这可能会发生。
同理,getContext()
也可以returnnull。
在这个可能相关的 post:
上,关于何时这些可以为 null 的讨论很好
- 在显示 Toast
.
之前进行空检查
但潜在的问题是架构之一 - 您的代码将 API activity 耦合到您的 UI,并假设您的 UI 状态的某些事情,即您假设当 API 调用 return 时,您的屏幕仍然对用户可见。
更好的解决方案是将 Retrofit 调用与 UI - put the API calls in a separate class that does not depend on the UI state.
分离
使用事件或发布-订阅框架从这个 API 包装器 class 返回到任何 UI 需要知道何时 API 调用 return秒。
EventBus
或 RxJava
将是 2 种常见的解决方案(LocalBroadcastManager
将是一种不太常见的方法)。
这将允许任何代码调用您的 API,并订阅在 API return 时收到通知。
它还允许您将 API 响应保存在(例如)本地数据库中,在这种情况下,您可以仅依靠 LiveData
模式来更新任何 UI那是必须的。
鉴于某些项目无法立即重新设计,可能需要变通办法。
上面提到的 null 检查解决方法很有用,因为应用程序将不再崩溃。不幸的是,这确实意味着用户不会收到有关失败的 API 呼叫的警报。
一种替代方法是创建您自己的 Application
subclass(许多项目已经这样做以初始化公共库)并提供静态访问此应用程序的方法 Context
。
然后您可以选择使用应用程序 Context
而不是片段中的应用程序来显示 Toast
。您可能会丢失从更具体的上下文中获得的任何特定样式,但优点是您的用户仍然可以看到 Toast
消息。
将您的 Application
暴露为单身人士已在 post:
上进行了很好的描述
if (isAdded()) {
Toast.makeText(getActivity(), "something", Toast.LENGTH_SHORT).show();
}
或者试试这个
if(getActivity() != null)
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();
两者在我的情况下都可以正常工作,因为在某些情况下 getActivity()
在片段分离时调用。
所以我们也必须解决这个问题。
我尝试在片段中显示吐司时,在少数设备上遇到错误。这个吐司通常是在改造响应失败时。 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)
你的activitycontext
在这行是空的:
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();// getActivity() is null
为避免崩溃,请使用:
if(getActivity() != null)
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();
有时,当片段未与 Activity 相关联时,getActivity() 或 getContext() 可能会产生空指针异常。所以使用onAttach方法
public class yourFragment extends Fragment {
Context context
@Override
public void onAttach(Context context) {
this.context = context;
super.onAttach(context);
}
}
将您的 getActivity()
更改为 getContext()
。试试下面给定的代码:
Toast.makeText(getContext(), "Connection Failure", Toast.LENGTH_LONG).show();
可能 getActivity()
在片段分离时调用。试试吧。
if (isAdded()) {
Toast.makeText(getActivity(), "something", Toast.LENGTH_SHORT).show();
}
根据 Fragment.getActivity()
的代码和 javadoc,您可以得到 null
returned:
/**
* 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();
}
尤其是当您的 Fragment 未附加到 activity 时(如
同理,getContext()
也可以returnnull。
在这个可能相关的 post:
上,关于何时这些可以为 null 的讨论很好Toast
.
但潜在的问题是架构之一 - 您的代码将 API activity 耦合到您的 UI,并假设您的 UI 状态的某些事情,即您假设当 API 调用 return 时,您的屏幕仍然对用户可见。
更好的解决方案是将 Retrofit 调用与 UI - put the API calls in a separate class that does not depend on the UI state.
分离使用事件或发布-订阅框架从这个 API 包装器 class 返回到任何 UI 需要知道何时 API 调用 return秒。
EventBus
或 RxJava
将是 2 种常见的解决方案(LocalBroadcastManager
将是一种不太常见的方法)。
这将允许任何代码调用您的 API,并订阅在 API return 时收到通知。
它还允许您将 API 响应保存在(例如)本地数据库中,在这种情况下,您可以仅依靠 LiveData
模式来更新任何 UI那是必须的。
鉴于某些项目无法立即重新设计,可能需要变通办法。
上面提到的 null 检查解决方法很有用,因为应用程序将不再崩溃。不幸的是,这确实意味着用户不会收到有关失败的 API 呼叫的警报。
一种替代方法是创建您自己的 Application
subclass(许多项目已经这样做以初始化公共库)并提供静态访问此应用程序的方法 Context
。
然后您可以选择使用应用程序 Context
而不是片段中的应用程序来显示 Toast
。您可能会丢失从更具体的上下文中获得的任何特定样式,但优点是您的用户仍然可以看到 Toast
消息。
将您的 Application
暴露为单身人士已在 post:
if (isAdded()) {
Toast.makeText(getActivity(), "something", Toast.LENGTH_SHORT).show();
}
或者试试这个
if(getActivity() != null)
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();
两者在我的情况下都可以正常工作,因为在某些情况下 getActivity()
在片段分离时调用。
所以我们也必须解决这个问题。