【问题标题】:Android Snackbar NullPointerException in Fragment片段中的Android Snackbar NullPointerException
【发布时间】:2015-08-14 16:31:43
【问题描述】:

我想在我的应用程序中添加一个基本的快餐栏,但我收到了一个我不知道原因的错误。

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

【问题讨论】:

  • 试试.setAction("Action", null).show(getActivity());
  • 它没有用。顺便说一句,我正在使用 android.support.v4.app.Fragment 是否意味着此错误。
  • 在 logcat 中可以清楚地看到 SnackBar 需要 Context
  • @MD 如果有官方库,则无需使用 GitHub 库(当然,除非它不适合您的应用程序)。 @Murat 也许您的 view 那时还没有初始化?从表面上看,这就是问题所在。

标签: android snackbar


【解决方案1】:

如果你的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();
}

【讨论】:

  • 或者你可以在你的片段中添加一个 CoordinatorLayout。
【解决方案2】:

1.将其移至 onActivityCreated 方法。

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

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

【讨论】:

【解决方案3】:

在我正在处理的代码库中,有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(),如果此方法返回null,您将得到问题中所示的NPE。

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

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

  2. 我最终自己做了什么:代码库中已经有一个 Builder pattern 样式包装器用于 Snackbar,所以我在构建器中分叉了 findSuitableParent() 并添加了一个检查以查看它是否返回 @ 987654342@ 在尝试致电 Snackbar.make() 之前。这样,Snackbar 构建器调用者就不必添加任何额外的检查。

【讨论】:

    【解决方案4】:

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

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

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

    尝试将您的snackbar show 方法放在片段的“onResume”中。 希望这会有所帮助。

    【讨论】:

      【解决方案5】:

      为什么要在 onCreate 中这样做?

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

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

      【讨论】:

      • 很好地尝试了规则 1。
      【解决方案6】:

      正如文档中所说,“Snackbar 将尝试找到一个父视图,以根据赋予视图的值来保存 Snackbar 的视图”。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-12
        • 2012-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-22
        • 2016-05-24
        • 1970-01-01
        相关资源
        最近更新 更多