Pourquoi le message d’erreur “Null check operator used on a null value” apparaît-il ?
Le message d’erreur « Null check operator used on a null value » est un message d’erreur de Flutter qui se produit lorsque vous utilisez l’opérateur de vérification de nullité “!” sur une valeur qui s’avère être nulle.
Pour comprendre un peu mieux le problème, voici les deux opérateurs de nullité, fournis par Flutter :
- ! (point d’exclamation) : Assure que la valeur n’est jamais nulle.
- ?. (point d’interrogation) : Vérifie si la valeur est nulle avant d’y accéder. Si elle est nulle, il renvoie null ou une valeur par défaut.
Puisque vous essayez d’accéder à une propriété ou d’appeler une méthode sur une variable qui n’a pas de valeur et qui portant est déclarée non null “!”, le code se bloque et ce message apparaît.
Par exemple, voici un code d’exemple faisant apparaître ce message d’erreur :
String? nom; // Déclaration d'une variable nullable
print(nom!.length); // Erreur "Null check operator used on a null value" car `nom` peut être null
Ici, nom est déclaré comme pouvant avoir une valeur null (opérateur “?” ajouté à ma classe String). Or, dans ma méthode print(), nom est déclaré comme non-nullable via l’opérateur “!”. Ma variable nom pouvant être nulle et n’ayant pas de valeur actuellement, le message d’erreur « Null check operator used on a null value » s’affiche donc.
Comment régler le message d’erreur “Null check operator used on a null value”
Il existe plusieurs manières de résoudre ce message d’erreur, soit en changeant d’opérateur, en attribuant une valeur à votre variable, ou en utilisant la méthode catch.
Changer d’opérateur de vérification de nullité
La première chose que vous pouvez faire pour régler ce problème est de changer l’opérateur de nullité de votre méthode :
String? nom;
print(nom?.length ?? 0); // Afficher 0 si nom est null, sinon afficher la longueur de nom
Ici, j’indique que ma variable nom peut avoir une valeur nulle via l’opérateur “?”. J’indique également quelle valeur lui donner, le cas échéant, ici 0.
Donner une valeur à votre variable
Ce message d’erreur apparaissant lorsqu’une variable est nulle, une autre solution pour éviter ce problème est de toujours donner une valeur par défaut à vos variables :
String nom = "";
print(nom.length);
Ici, j’attribue une chaîne de caractère vide, comme valeur à ma variable nom. Je n’ai donc pas de message d’erreur au moment de l’afficher dans la console.
Utiliser la méthode try & catch
Utiliser une méthode try & catch, n’empêchera pas d’avoir une erreur si votre valeur est null, mais permettra au moins au code de ne pas se bloquer et de devoir relancer l’application. Je vous conseille donc d’en user le plus possible lorsque vous mettez en place des fonctions qui peuvent renvoyer une erreur :
String? nom;
try {
print(nom!.length);
} catch (e) {
print("Erreur : $e"); // Afficher le message d'erreur
}
Ici, j’essaye d’afficher la longueur de ma variable nom dans ma méthode try. Mais celle-ci n’a pas de valeur. J’ai donc mis en place une méthode catch, qui va renvoyer un message d’erreur dans ma console et quitter ma méthode, plutôt que de bloquer l’application.
Quand puis-je avoir une erreur de type null check operator ?
L’erreur null check operator, peut subvenir avec tout un tas de widgets différents. En voici quelques exemples.
Erreur avec Navigator
ou MediaQuery
Cette erreur se produit souvent lorsque vous accédez à un BuildContext de manière asynchrone, sans vérifier si le widget est toujours monté.
Future<void> foo() async {
// Opération asynchrone
await compute();
// Accès à 'context' sans vérification
MediaQuery.of(context).size;
Navigator.of(context).pop();
}
Solution
Avant d’accéder au contexte, vérifiez si le widget est toujours monté à l’aide de la propriété mounted
:
Future<void> foo() async {
await compute();
// Vérifiez si le widget est monté
if (mounted) {
MediaQuery.of(context).size;
Navigator.of(context).pop();
}
}
Erreur avec Colors
Une autre erreur fréquente survient lorsque vous essayez d’accéder à une nuance inexistante d’une couleur, comme :
Colors.blueAccent.shade60
Dans le code source de Flutter, cette opération utilise le null check operator, ce qui peut provoquer une erreur si la nuance demandée n’existe pas :
Color get shade50 => this[60]!; // <-- Opérateur "!"
Solution
Avant d’accéder au contexte, vérifiez si le widget est toujours monté à l’aide de la propriété mounted
:
Future<void> foo() async {
await compute();
// Vérifiez si le widget est monté
if (mounted) {
MediaQuery.of(context).size;
Navigator.of(context).pop();
}
}
Erreur avec FutureBuilder
ou StreamBuilder
Lorsque vous travaillez avec des FutureBuilder
ou StreamBuilder
, l’erreur peut apparaître si vous ne spécifiez pas de type ou si vous manipulez incorrectement les données.
Solution 1 : Spécifiez un type explicite
Déclarez le type des données attendues dans le FutureBuilder
ou StreamBuilder
:
FutureBuilder<List<int>>( // Type explicitement défini
future: _listOfInt(),
builder: (_, snapshot) {
if (snapshot.hasData) {
List<int> myList = snapshot.data!; // Données sécurisées
}
return Container();
},
)
Solution 2 : Utilisez as
pour caster les données
Vous pouvez également caster les données pour éviter l’erreur :
FutureBuilder(
future: _listOfInt(),
builder: (_, snapshot) {
if (snapshot.hasData) {
var myList = snapshot.data! as List<int>; // Cast explicite
}
return Container();
},
)
Erreur avec TextEditingController
Lors de l’utilisation de TextEditingController
pour des champs de texte, l’erreur peut apparaître si vous essayez d’accéder à une propriété après avoir détruit le contrôleur.
@override
void dispose() {
_textController.dispose();
print(_textController.text); // Erreur !
super.dispose();
}
Solution
Ne tentez pas d’utiliser le contrôleur après avoir appelé dispose
:
@override
void dispose() {
print(_textController.text); // Utilisation avant `dispose`
_textController.dispose();
super.dispose();
}
Erreur avec List
ou Map
nullables
Les collections peuvent également provoquer cette erreur si vous utilisez l’opérateur !
sur une clé ou un index potentiellement null :
List<String>? myList;
String value = myList![0]; // Erreur si `myList` est null
Solution
Vérifiez la nullité avant d’accéder à l’élément :
if (myList != null && myList.isNotEmpty) {
String value = myList[0];
}
Erreur avec GlobalKey
Lorsque vous utilisez un GlobalKey
pour accéder à l’état d’un widget, le widget peut ne pas exister, ce qui entraîne l’erreur.
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
void submit() {
_formKey.currentState!.validate(); // Erreur si currentState est null
}
Solution
Vérifiez si currentState
n’est pas null :
void submit() {
if (_formKey.currentState != null) {
_formKey.currentState!.validate();
}
}