片段中的Android Snackbar NullPointerException

我想在我的应用程序中添加一个基本的快餐栏,但我收到一个错误,我无法弄清楚为什么。

我在Fragment的onCreateView()方法中添加了这段代码。

Snackbar.make(view, "Snackbar", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); 

并收到此错误:

 06-01 10:26:09.955 1232-1232/? E/ActivityThread﹕ Failed to find provider info for me.muraterdogan.watchme.MetricaContentProvider 06-01 10:26:10.075 1232-1447/? E/ActivityThread﹕ Failed to find provider info for me.muraterdogan.watchme.YPLContentProvider 06-01 10:33:55.044 6646-6646/? E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: me.muraterdogan.watchme, PID: 6646 java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.view.ViewGroup.getContext()' on a null object reference at android.support.design.widget.Snackbar.(Snackbar.java:116) at android.support.design.widget.Snackbar.make(Snackbar.java:140) at me.muraterdogan.watchme.fragments.TrendingFragment.GetData(TrendingFragment.java:90) at me.muraterdogan.watchme.fragments.TrendingFragment.onCreateView(TrendingFragment.java:83) ... 

如果将Fragment添加到现有活动中(请记住,您可以通过xml添加它),则应将SnackBar的方法调用到Fragment的onActivityCreated()方法中。

 @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Snackbar.make(view, "Snackbar", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } 

1.将其移动到onActivityCreated方法。

2.在make方法中使用getView(),如下所示:

 Snackbar.make(getView(), "Snackbar", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); 

在我正在研究的代码库中,在异步方法回调中显示了Snackbar ,例如网络调用的error handling程序。 当Snackbar被创建时,它将要去的Fragment不再被附加,并且getView()返回的View没有CoordinatorLayoutFrameLayout Snackbar想要在视图的层次结构中。

特别是, Snackbar中的私有findSuitableParent()方法遍历层次结构:

 private static ViewGroup findSuitableParent(View view) { ViewGroup fallback = null; do { if (view instanceof CoordinatorLayout) { // We've found a CoordinatorLayout, use it return (ViewGroup) view; } else if (view instanceof FrameLayout) { if (view.getId() == android.R.id.content) { // If we've hit the decor content view, then we didn't find a CoL in the // hierarchy, so use it. return (ViewGroup) view; } else { // It's not the content view but we'll use it as our fallback fallback = (ViewGroup) view; } } if (view != null) { // Else, we will loop and crawl up the view hierarchy and try to find a parent final ViewParent parent = view.getParent(); view = parent instanceof View ? (View) parent : null; } } while (view != null); // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback return fallback; } 

将此方法的结果传递给Snackbar构造函数,该构造函数对其调用getContext() ,如果此方法返回null则会获得问题中所见的NPE。

有几种方法可以解决这个问题,假设在附加片段中有一个CoordinatorLayoutFrameLayout的幸福案例仍然存在:

  1. 首先检查isDetached()确保您的片段没有分离。

  2. 我最终做了什么:代码库中的Snackbar已经有一个Builder模式样式包装器,所以我在构建器中分叉了findSuitableParent() ,并在尝试调用Snackbar.make()之前添加了一个检查以查看它返回!= null Snackbar.make() 。 这样,Snackbar构建器调用者不必添加任何其他检查。

通过过程,小吃店搜索视图。

  • 您使用了片段视图
  • 但片段视图本身尚未附加,因为尚未调用片段的onAttach。

因此,在运行时,应用程序本身并不真正知道您实际上是在引用片段的视图。

尝试将快餐栏show方法放在片段的“onResume”上。 希望这可以帮助。

你为什么要在onCreate中这样做?

另外,请确保遵循以下几条规则:

  1. 确保您的主Activityinheritance自AppCompatActivity,因为这是使用支持库所必需的。
  2. 确保您传递的视图实际存在(这就是为什么我问你为什么要在onCreate中执行此操作以及为什么不在之后?)

正如文档中所说“Snackbar将尝试查找父视图以从查看的值中保存Snackbar的视图”。

所以你可以传递任何附加的视图。