web-dev-qa-db-fra.com

Android Snackbar NullPointerException in Fragment

Je souhaite ajouter une barre de base à mon application, mais j'ai reçu une erreur indiquant que je ne pouvais pas comprendre pourquoi.

J'ai ajouté ce code dans la méthode onCreateView () de mon fragment.

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

Et a reçu cette erreur:

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)
...
14
Murat Erdogan

Si votre fragment est ajouté à une activité existante (n'oubliez pas que vous pouvez l'ajouter via xml), vous devez appeler la méthode de SnackBar dans la méthode onActivityCreated () du fragment.

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

1. déplacez-le vers la méthode onActivityCreated.

2.try à utiliser getView () dans la méthode make comme suit:

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

Dans une base de code sur laquelle je travaillais, il y avait Snackbars affichés dans les rappels de méthode asynchrones tels que les gestionnaires d'erreur d'un appel réseau. Lorsque la variable Snackbar était créée, la Fragment qu'elle allait partir n'était plus attachée et sa View telle que renvoyée par getView() n'avait pas de CoordinatorLayout ou FrameLayoutSnackbar veut avoir dans la hiérarchie de la vue.

En particulier, c'est la méthode privée findSuitableParent() dans Snackbar qui traverse la hiérarchie:

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

Le résultat de cette méthode est transmis au constructeur Snackbar qui appelle getContext(), et si cette méthode renvoie null, vous obtenez le NPE comme indiqué dans la question.

Il existe deux manières de résoudre le problème, en supposant que le cas heureux de la présence d'une variable CoordinatorLayout ou FrameLayout dans les fragments attachés est toujours valable:

  1. Assurez-vous que votre fragment n'est pas détaché en vérifiant d'abord isDetached().

  2. Ce que j'ai fini par faire moi-même: il y avait déjà un Générateur modèle styling wrapper pour la variable Snackbar dans la base de code, alors j’ai créé la fonction findSuitableParent() dans le générateur et ajouté une coche pour qu’elle renvoie != null avant de tenter d’appeler Snackbar.make(). De cette façon, les appelants du constructeur de la barre de progression n'ont pas à ajouter de vérifications supplémentaires.

3
laalto

Par le processus, le snack-bar cherche la vue. 

  • Vous avez utilisé la vue des fragments
  • Mais la vue fragment elle-même n'est pas encore attachée, car onAttach du fragment N'est pas encore appelé.

Ainsi, l'application elle-même ne sait pas vraiment, au moment de l'exécution, que vous faisiez réellement référence à la vue du fragment.

Essayez de placer votre méthode d’émission de snackbar sur le "résumé" du fragment . J'espère que cela vous aidera.

2
gorbos

Pourquoi faites-vous cela dans onCreate?

De plus, assurez-vous de suivre quelques règles:

  1. Assurez-vous que votre activité principale hérite de AppCompatActivity, car cela est nécessaire pour utiliser les bibliothèques de support.
  2. Assurez-vous que la vue que vous transmettez existe réellement (c'est pourquoi je vous demande pourquoi vous faites cela dans onCreate et pourquoi pas après?)
1
AkiAki007

Comme indiqué dans la documentation, "Snackbar essaiera de trouver une vue parente pour conserver la vue de Snackbar à partir de la valeur donnée à voir".

Ainsi, vous pouvez passer n’importe quelle vue qui est attachée pour le moment.

0
Daniel Arroyo