Android Snackbar NullPointerException in Fragment

 ̄綄美尐妖づ 提交于 2019-12-03 23:56:50

If your Fragment is added to existing activity(Remember you can add it through xml), you should call the SnackBar's method into the onActivityCreated() method of the Fragment.

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

1.move it to onActivityCreated method.

2.try to use getView() in make method like following:

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

In a codebase I was working on, there were Snackbars shown in asynchronous method callbacks such as error handlers of a network call. When the Snackbar was being made, the Fragment it was going to go was no longer attached and its View as returned by getView() did not have a CoordinatorLayout or FrameLayout Snackbar wants to have in the view's hierarchy.

In particular, it's the private findSuitableParent() method in Snackbar that traverses the hierarchy:

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;
}

The result of this method is passed to Snackbar constructor that calls getContext() on it, and if this method returns null you get the NPE as seen in the question.

There are a couple of ways to fix the problem, assuming the happy case of having a CoordinatorLayout or FrameLayout in attached fragments still holds:

  1. Make sure your fragment is not detached by checking isDetached() first.

  2. What I ended up doing myself: There was already a Builder pattern styling wrapper for the Snackbar in the codebase, so I forked the findSuitableParent() in the builder and added a check to see it returns != null before attempting to call Snackbar.make(). This way the Snackbar builder callers did not have to add any additional checks.

By process, the snack bar searches for the view.

  • You used the fragments view
  • But the fragment view itself is not yet attached, since onAttach of the fragment is not yet called.

So the app itself doesn't really know, on runtime, that you were actually referring to the view of the fragment.

Try placing your snackbar show method at the "onResume" of the fragment. Hope this helps.

Why are you doing this within onCreate?

Additionally make sure that you are following a couple of rules:

  1. Ensure that your main Activity inherits from AppCompatActivity as that is necessary for using the Support libs.
  2. Ensure that the view that you are passing actually exists (this is why I'm asking why you're doing this in onCreate and why not after?)

As the documentation says "Snackbar will try and find a parent view to hold Snackbar's view from the value given to view".

So you can pass any view that is attached at the moment.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!