El mismo comportamiento que está experimentando incluso se conoce como un "caso complicado" en la documentación de Flutter .
Como arreglar
El problema se soluciona de diferentes maneras, como puede ver en otras respuestas publicadas aquí. Por ejemplo, la pieza de documentación a la que me refiero resuelve el problema mediante el uso de un Builder
que crea
un interno BuildContext
para que los onPressed
métodos puedan referirse al Scaffold
con Scaffold.of()
.
Por lo tanto, una forma de llamar showSnackBar
desde Scaffold sería
@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.')
));
}
);
}
)
);
}
Ahora algunos detalles para el lector curioso
Yo mismo encontré bastante instructivo para explorar la documentación de Flutter simplemente ( Android Studio ) colocando el cursor en una pieza de código ( clase de Flutter , método, etc.) y presionando ctrl + B para mostrar la documentación de esa pieza específica.
El problema particular que enfrenta se menciona en el documento de BuildContext , donde se puede leer
Cada widget tiene su propio BuildContext , que se convierte en el padre del widget devuelto por la [...] función. Build .
Entonces, esto significa que, en nuestro caso, el contexto será el padre de nuestro widget Scaffold cuando se cree (!). Además, el docu para Scaffold.of dice que regresa
El estado de la instancia [ Scaffold ] más cercana de esta clase que encierra el contexto dado.
Pero en nuestro caso, el contexto no encierra (todavía) un Andamio (aún no se ha construido). ¡Ahí es donde entra en acción Builder !
Una vez más, el docu nos ilumina. Allí podemos leer
[La clase Builder, es simplemente] Un widget platónico que llama a un cierre para obtener su widget hijo.
Oye, espera un momento, ¿qué? Ok, lo admito: eso no está ayudando mucho ... Pero es suficiente decir (siguiendo otro hilo SO ) que
El propósito de la clase Builder es simplemente construir y devolver widgets secundarios.
¡Así que ahora todo queda claro! Al llamar a Builder dentro de Scaffold , estamos construyendo el Scaffold para poder obtener su propio contexto, y armados con ese contexto interno , finalmente podemos llamar a Scaffold.of (innerContext)
Sigue una versión anotada del código anterior
@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.')
));
}
);
}
)
);
}