Android 片段中的 Snackbar NullPointerException

Android Snackbar NullPointerException in Fragment

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

我在 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.<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)
...

为什么要在 onCreate 中执行此操作?

此外,请确保您遵守几条规则:

  1. 确保您的主要 Activity 继承自 AppCompatActivity,因为这是使用支持库所必需的。
  2. 确保你传递的视图确实存在(这就是为什么我要问你为什么在 onCreate 中这样做,为什么不在之后?)

如果你的Fragment是添加到现有的activity(记住你可以通过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.move 它到 onActivityCreated 方法。

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

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

按流程,小吃店搜索视图。

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

所以应用程序本身并不知道,在运行时,你实际上指的是片段的视图。

尝试将您的 snackbar show 方法放在片段的 "onResume" 处。 希望这有帮助。

如文档所述"Snackbar will try and find a parent view to hold Snackbar's view from the value given to view"。

因此您可以传递当前附加的任何视图。

在我正在处理的代码库中,异步方法回调中显示了 Snackbars,例如网络调用的错误处理程序。当制作 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(),如果此方法 returns null 您将获得 NPE,如问题。

有几种方法可以解决这个问题,假设在附加片段中有 CoordinatorLayoutFrameLayout 的快乐情况仍然成立:

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

  2. 我最终自己做了什么:代码库中已经有 SnackbarBuilder pattern 样式包装器,所以我在构建器并在尝试调用 Snackbar.make() 之前添加了一个检查以查看它 returns != null。这样 Snackbar 构建器调用者就不必添加任何额外的检查。