NullPointerException dans un fragment Kotlin : comment le vaincre sans perdre la raison

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : « J'ai tout fait selon le tutoriel, mais l'application plante ! »

\n

Si vous venez de commencer votre parcours dans le développement Android avec Kotlin, vous avez probablement déjà rencontré ce moment. Vous écrivez du code en suivant un tutoriel, vous lancez l'application… et plantage. Dans les logs — le fameux java.lang.NullPointerException (ou son équivalent Kotlin). Et le message : « Cannot read field… because the view is null ».

\n

C'est une vraie douleur qui a rassemblé des milliers de vues sur Stack Overflow. Aujourd'hui, nous allons l'analyser une fois pour toutes. Pourquoi NullPointerException se produit-elle lors de l'accès à une View dans un Fragment en Kotlin ? Et surtout, comment la corriger pour que vous dormiez tranquille.

\n

C'est parti !

\n\n

Pourquoi l'erreur se produit-elle ? La racine du mal — le cycle de vie

\n

La principale raison pour laquelle les débutants obtiennent une NullPointerException dans un Fragment Kotlin est la méconnaissance du cycle de vie du fragment. Dans une Activity, c'est simple : onCreate — et c'est parti. Dans un Fragment, c'est plus complexe.

\n

Le fragment passe par plusieurs étapes :

\n
    \n
  • onCreateView() — ici, la mise en page est gonflée (créée).
  • \n
  • onViewCreated() — ici, la View existe déjà avec certitude.
  • \n
  • onDestroyView() — la View est détruite (par exemple, lors de la rotation de l'écran).
  • \n
\n

L'erreur la plus courante est la tentative d'accéder à la View avant que le fragment n'ait créé sa mise en page. Par exemple, dans le constructeur ou dans onCreate() du fragment. À ce moment-là, view est égal à null — d'où le plantage.

\n

La deuxième raison est une fuite de références. Vous avez sauvegardé une référence à la View dans une variable, puis le fragment a été recréé, et l'ancienne référence ne mène nulle part.

\n\n

Exemple typique : à quoi ressemble le problème dans le code

\n

Imaginez que vous ayez un fragment simple avec un champ de texte :

\n
class MyFragment : Fragment() {\n\n    private lateinit var myTextView: TextView\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        // ERREUR ! La view n'existe pas encore ici\n        myTextView = requireView().findViewById(R.id.my_text_view)\n        myTextView.text = "Bonjour !"\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        return inflater.inflate(R.layout.fragment_my, container, false)\n    }\n}
\n

Ce code plantera avec une NullPointerException, car requireView() dans onCreate() retourne null. La View n'a pas encore été créée !

\n\n

3 méthodes efficaces pour corriger l'erreur

\n

Examinons trois approches qui résoudront à coup sûr le problème de l'accès à la View dans un Fragment.

\n\n

Méthode 1 : Déplacer le code dans onViewCreated()

\n

La manière la plus simple et la plus correcte est d'attendre le moment où la View existe avec certitude. La méthode onViewCreated() est appelée immédiatement après la création de la mise en page.

\n
class MyFragment : Fragment() {\n\n    private lateinit var myTextView: TextView\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        return inflater.inflate(R.layout.fragment_my, container, false)\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        // Maintenant, la view n'est définitivement pas null !\n        myTextView = view.findViewById(R.id.my_text_view)\n        myTextView.text = "Tout fonctionne !"\n    }\n}
\n

Avantages : simple, clair, fonctionne toujours.
\nInconvénients : il faut se souvenir de lateinit var et ne pas oublier de nullifier les références dans onDestroyView() (sinon, une fuite mémoire est possible).

\n\n

Méthode 2 : Utiliser le View Binding (recommandé)

\n

Blogs

Book Recommendations