Lo stesso comportamento che si sta verificando viene anche chiamato "caso complicato" nella documentazione di Flutter .
Come risolvere
Il problema è stato risolto in diversi modi, come puoi vedere dalle altre risposte pubblicate qui. Ad esempio, la documentazione a cui mi riferisco risolve il problema utilizzando una funzione Builder
che crea
un interno in BuildContext
modo che i onPressed
metodi possano fare riferimento al Scaffold
con Scaffold.of()
.
Quindi sarebbe un modo per chiamare showSnackBar
da Scaffold
@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.')
));
}
);
}
)
);
}
Ora qualche dettaglio per il curioso lettore
Io stesso ho trovato abbastanza istruttivo esplorare la documentazione di Flutter semplicemente ( Android Studio ) impostando il cursore su un pezzo di codice ( Flutter classe , metodo, ecc.) E premendo ctrl + B per mostrare la documentazione per quel pezzo specifico.
Il problema particolare che stai affrontando è menzionato nel documento per BuildContext , dove può essere letto
Ogni widget ha il suo BuildContext , che diventa il genitore del widget restituito dalla funzione [...].
Quindi, questo significa che nel nostro caso il contesto sarà il genitore del nostro widget Scaffold quando verrà creato (!). Inoltre, il documento per Scaffold.of afferma che ritorna
Lo stato dall'istanza [ Scaffold ] più vicina di questa classe che racchiude il contesto dato.
Ma nel nostro caso, il contesto non racchiude (ancora) uno Scaffold (non è stato ancora costruito). C'è dove Builder entra in azione!
Ancora una volta, il documento ci illumina. Lì possiamo leggere
[La classe Builder è semplicemente] Un widget platonico che chiama una chiusura per ottenere il suo widget figlio.
Ehi, aspetta un momento, cosa !? Ok, lo ammetto: questo non aiuta molto ... Ma è sufficiente dirlo (seguendo un altro thread SO )
Lo scopo della classe Builder è semplicemente quello di creare e restituire widget figlio.
Quindi ora tutto diventa chiaro! Chiamando Builder all'interno di Scaffold stiamo costruendo lo Scaffold per essere in grado di ottenere il suo contesto, e armato con quel InnerContext possiamo finalmente chiamare Scaffold.of (innerContext)
Segue una versione annotata del codice sopra
@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.')
));
}
);
}
)
);
}