Android Snackbar在Fragment中出现空指针异常

14

我想在我的应用程序中添加一个基本的 Snackbar,但是我收到了一个错误,我无法弄清楚原因。

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

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.<init>(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)
...

1
尝试使用.setAction("Action", null).show(getActivity()); - M D
http://williammora.com/snackbar-android-library/ - M D
它没有起作用。顺便说一下,如果这个错误有什么意义的话,我正在使用android.support.v4.app.Fragment。 - Murat Erdogan
1
@MD 当官方提供了一个库时,就不需要使用GitHub库(当然,除非它不适合你的应用程序)。@Murat也许在那个时候你的“view”还没有初始化?从外表看,这就是问题所在。 - Roman Kotenko
@MD 但这是一个不同的库。我正在尝试使用安卓支持库。 - Murat Erdogan
显示剩余4条评论
6个回答

19
如果您的Fragment被添加到现有的Activity中(请记住,您可以通过xml添加它),则应在Fragment的onActivityCreated()方法中调用SnackBar的方法。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Snackbar.make(view, "Snackbar", Snackbar.LENGTH_LONG)
        .setAction("Action", null).show();
}

3
你可以在你的碎片中添加一个CoordinatorLayout。 - Desmond Lua

13

1. 将其移动到onActivityCreated方法中。

2. 在make方法中尝试像以下这样使用getView():

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

也可以尝试使用以下链接:https://dev59.com/jVwY5IYBdhLWcg3ws5oF - Mr-IDE

3
在我工作的代码库中,异步方法回调(例如网络调用的错误处理程序)中显示了 Snackbar。当制作 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的happy case:
  1. 通过先检查isDetached()来确保未分离您的片段。

  2. 我自己最终所做的:在代码库中已经有一个SnackbarBuilder pattern样式包装器,所以我在构建器中分叉了findSuitableParent(),并添加了一个检查以查看它返回的内容 != null ,然后才尝试调用Snackbar.make()。这样Snackbar builder的调用者就不必添加任何附加检查。


2

在这个过程中,小吃店正在寻找视图。

  • 您使用了碎片视图
  • 但是,由于尚未调用片段的onAttach方法,因此片段视图本身尚未附加。

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

尝试将Snackbar显示方法放置在片段的“onResume”中。

希望能帮到您。

1

为什么你要在onCreate方法中执行这个操作?

此外,请确保遵循以下几点规则:

  1. 确保你的主Activity继承自AppCompatActivity,因为这是使用支持库所必需的。
  2. 确保你传递的视图实际上存在(这就是我问为什么你在onCreate之后而不是之前执行该操作的原因)。

规则1很不错,你尝试得很好。 - ashubuntu

0
根据文档所述,“Snackbar将尝试查找父视图以从给定的值中持有Snackbar的视图”。
因此,您可以传递任何当前已附加的视图。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接