web-dev-qa-db-fra.com

DialogFragment getActivity () "peut être nul" avertissement de peluche dans AndroidStudio 3.0.1

La question la plus proche que je puisse trouver à ce sujet est Avertissements de lint Android Studio 3.0 pour les références à une activité , mais cela n’aide en rien.

Avec AndroidStudio 3.0.1, j'ai une DialogFragment dans laquelle je fais les choses habituelles:

    @Override
    @NonNull
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        ...

J'ai un peluche qui me prévient que Argument 'getActivity()' might be null

Je comprends pourquoigetActivity() peut être nul et je comprends comment l'inspection des peluches le sait (à partir de l'annotation @Nullable). 

Ma question est la suivante: c’est très bien et bon que getActivity() soit nul, mais comment suis-je supposé gérer cela avec élégance et propreté? onCreateDialogdoit renvoyer une Dialog (en raison de l'annotation @Nullable de la superclasse) afin que je doit disposer du contexte d'activité pour le créer. 

Je peux supposer que onCreateDialog ne sera jamais appelé si DialogFragment n'est pas associé à une activité, mais quand même - comment puis-je résoudre le problème de la peluche désordonnée?

22
Trevor

La réponse de @Niklas explique pourquoi vous recevez cet avertissement maintenant. J'aimerais partager mes réflexions sur ce que vous devriez réellement faire.

Tout d'abord, cette annulation ajoutée ne fait qu'exposer l'ancienne déficience de conception qui était présente toutes ces années - cette méthode peut toujours retourner à null (par exemple, un fragment détaché). 

Je préférerais s’ils annotaient la valeur de retour sous la forme @NonNull et lançaient une exception en interne si cette méthode est appelée lorsque l’activité est réellement nulle, mais je comprends qu’elle romprait la compatibilité avec les versions antérieures et serait donc très risquée quiconque appelle cette méthode lorsque l’activité peut en réalité être nulle).

Alors, que devrions-nous faire à ce sujet?

Tout d'abord, puisque la fonctionnalité n'a pas du tout changé, si le code en question fonctionnait déjà, alors faites ce que @CommonsWare a suggéré: supprimer l'avertissement ou l'ignorer.

Vous pouvez également encapsuler chaque appel dans un contrôle nul avec, par exemple, exception.

Ce que je vais faire, cependant, est de mettre cette méthode dans mon BaseDialog (qui est étendu par tous les autres dialogues):

protected FragmentActivity getActivityNonNull() {
    if (super.getActivity() != null) {
        return super.getActivity();
    } else {
        throw new RuntimeException("null returned from getActivity()");
    }
}

Notez que toutes ces options indiquent effectivement que vous ne vous attendez pas vraiment à ce que la valeur NULL soit renvoyée et que l’application se bloque correctement si cela se produit. C'est pourquoi j'ai dit que je préférerais que cela soit pris en charge par le code de bibliothèque.

Modifier:

Une nouvelle méthode a été ajoutée pour prendre en charge Fragments - requireActivity () . Cette méthode est équivalente à getActivityNonNull() décrite ci-dessus (bien qu'elle jette IllegalStateException si elle n'est pas attachée à Activity).

Utilisez cette méthode au lieu de getActivity() et vous devriez être bon.

21
Vasiliy

Il s’agit d’un doublon - des avertissements de peluche pour Android Studio 3.0 concernant les références à une activité .

tldr; getActivity() a obtenu avec Support lib 27.0.0 l'annotation @Nullable et les outils d'analyse statiques le récupèrent maintenant.

1
Niklas

Ces méthodes ont été ajoutées à la révision 27.1.0 Version: les fragments ont maintenant les méthodes requireContext(), requireActivity(), requireHost() et requireFragmentManager(), qui renvoient un objet NonNull des méthodes get équivalentes ou émettent une exception IllegalStateException.

1
Mohammad Mirzakhani

Pour ceux d'entre vous qui veulent voir le code source de la méthode requireActivity():

 @NonNull 
 public final FragmentActivity requireActivity() { 
     FragmentActivity activity = this.getActivity();
     if (activity == null) { 
         throw new IllegalStateException(
             "Fragment " + this + " not attached to an activity."
         );
     } else {
         return activity; 
     }
 } 
0
Avid Programmer