Le comportement même que vous rencontrez est même qualifié de "cas délicat" dans la documentation Flutter .
Comment réparer
Le problème est résolu de différentes manières, comme vous pouvez le voir dans d'autres réponses publiées ici. Par exemple, la documentation à laquelle je fais référence résout le problème en utilisant un Builder
qui crée
un interne BuildContext
afin que les onPressed
méthodes puissent faire référence au Scaffold
avec Scaffold.of()
.
Ainsi, un moyen d'appeler showSnackBar
depuis Scaffold serait
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo')),
body: Builder(
builder: (BuildContext innerContext) {
return FlatButton(
child: Text('BUTTON'),
onPressed: () {
Scaffold.of(innerContext).showSnackBar(SnackBar(
content: Text('Hello.')
));
}
);
}
)
);
}
Maintenant quelques détails pour le lecteur curieux
J'ai moi-même trouvé assez instructif d'explorer la documentation Flutter simplement ( Android Studio ) en plaçant le curseur sur un morceau de code ( classe Flutter , méthode, etc.) et en appuyant sur ctrl + B pour afficher la documentation de ce morceau spécifique.
Le problème particulier auquel vous êtes confronté est mentionné dans le docu de BuildContext , où peut être lu
Chaque widget a son propre BuildContext , qui devient le parent du widget retourné par la fonction [...]. Build .
Donc, cela signifie que dans notre cas, le contexte sera le parent de notre widget Scaffold lors de sa création (!). De plus, le docu pour Scaffold.of dit qu'il renvoie
L'état de l' instance [ Scaffold ] la plus proche de cette classe qui englobe le contexte donné.
Mais dans notre cas, le contexte ne renferme pas (encore) un échafaudage (il n'a pas encore été construit). C'est là que Builder entre en action!
Une fois de plus, le docu nous éclaire. Là on peut lire
[La classe Builder, est simplement] Un widget platonique qui appelle une fermeture pour obtenir son widget enfant.
Hé, attendez un instant, quoi!? Ok, j'avoue: ça n'aide pas beaucoup ... Mais il suffit de dire (suite à un autre fil SO ) que
Le but de la classe Builder est simplement de créer et de renvoyer des widgets enfants.
Alors maintenant, tout devient clair! En appelant Builder à l' intérieur de Scaffold, nous construisons le Scaffold afin de pouvoir obtenir son propre contexte, et armés de ce innerContext, nous pouvons enfin appeler Scaffold.of (innerContext)
Une version annotée du code ci-dessus suit
@override
Widget build(BuildContext context) {
// here, Scaffold.of(context) returns null
return Scaffold(
appBar: AppBar(title: Text('Demo')),
body: Builder(
builder: (BuildContext innerContext) {
return FlatButton(
child: Text('BUTTON'),
onPressed: () {
// here, Scaffold.of(innerContext) returns the locally created Scaffold
Scaffold.of(innerContext).showSnackBar(SnackBar(
content: Text('Hello.')
));
}
);
}
)
);
}