Das Verhalten, das Sie erleben, wird in der Flutter- Dokumentation sogar als "kniffliger Fall" bezeichnet .
Wie repariert man
Das Problem wird auf verschiedene Arten behoben, wie Sie aus anderen hier veröffentlichten Antworten ersehen können. Zum Beispiel löst die Dokumentation, auf die ich mich beziehe, das Problem durch die Verwendung von a, Builder
das erstellt
ein inneres, BuildContext
damit sich die onPressed
Methoden auf das Scaffold
mit beziehen können Scaffold.of()
.
Ein Weg, um showSnackBar
von Scaffold aus anzurufen, wäre also
@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.')
));
}
);
}
)
);
}
Nun ein Detail für den neugierigen Leser
Ich selbst fand es sehr lehrreich, die Flutter- Dokumentation zu erkunden, indem ich einfach ( Android Studio ) den Cursor auf einen Code ( Flutter- Klasse, Methode usw.) setzte und Strg + B drückte, um die Dokumentation für diesen bestimmten Teil anzuzeigen.
Das spezielle Problem, mit dem Sie konfrontiert sind, wird im Dokument für BuildContext erwähnt , in dem es gelesen werden kann
Jedes Widget verfügt über einen eigenen BuildContext , der zum übergeordneten Element des Widgets wird, das von der Build-Funktion [...] zurückgegeben wird.
So bedeutet dies , dass in unserem Fall Zusammenhang wird die Mutter unseres Scaffold - Widget , wenn es erstellt wird (!). Weiter sagt das Dokument für Scaffold.of , dass es zurückkehrt
Der Status der nächsten [ Scaffold ] -Instanz dieser Klasse, die den angegebenen Kontext einschließt.
In unserem Fall enthält der Kontext jedoch (noch) kein Gerüst (es wurde noch nicht erstellt). Hier kommt Builder zum Einsatz!
Wieder einmal beleuchtet uns das Dokument. Dort können wir lesen
[Die Builder-Klasse ist einfach] Ein platonisches Widget, das einen Abschluss aufruft, um sein untergeordnetes Widget zu erhalten.
Hey, warte einen Moment, was? Ok, ich gebe zu: das hilft nicht viel ... Aber es reicht zu sagen (nach einem anderen SO-Thread ), dass
Der Zweck der Builder- Klasse besteht einfach darin, untergeordnete Widgets zu erstellen und zurückzugeben.
Jetzt wird alles klar! Indem wir Builder in Scaffold aufrufen , erstellen wir das Scaffold, um seinen eigenen Kontext zu erhalten, und mit diesem inneren Kontext können wir schließlich Scaffold.of (innerContext) aufrufen.
Eine kommentierte Version des obigen Codes folgt
@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.')
));
}
);
}
)
);
}