Pasar datos entre pantallas en Flutter
Mientras aprendo Flutter, llegué a la navegación. Quiero pasar datos entre pantallas de manera similar a pasar datos entre actividades en Android y pasar datos entre controladores de vista en iOS . ¿Cómo lo hago en Flutter?
Preguntas relacionadas:
- La mejor manera de pasar datos entre widgets en Flutter
- ¿Aleteo pasa datos entre widgets?
- Flutter/Cómo pasar y obtener datos entre Statefulwidget
Esta respuesta cubrirá tanto el paso de datos hacia adelante como el paso de datos hacia atrás. A diferencia de las actividades de Android y los ViewControllers de iOS, las diferentes pantallas en Flutter son solo widgets. Navegar entre ellos implica crear algo llamado ruta y usar Navigator
para insertar y sacar las rutas de la pila.
Pasar datos a la siguiente pantalla
Para enviar datos a la siguiente pantalla, haga lo siguiente:
Haga que el
SecondScreen
constructor tome un parámetro para el tipo de datos que desea enviarle. En este ejemplo particular, los datos se definen como unString
valor y se configuran aquí conthis.text
.class SecondScreen extends StatelessWidget { final String text; SecondScreen({Key key, @required this.text}) : super(key: key); ...
Luego use
Navigator
en elFirstScreen
widget para enviar una ruta alSecondScreen
widget. Pones los datos que quieres enviar como parámetro en su constructor.Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(text: 'Hello',), ));
El código completo main.dart
está aquí:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Flutter',
home: FirstScreen(),
));
}
class FirstScreen extends StatefulWidget {
@override
_FirstScreenState createState() {
return _FirstScreenState();
}
}
class _FirstScreenState extends State<FirstScreen> {
// this allows us to access the TextField text
TextEditingController textFieldController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('First screen')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(32.0),
child: TextField(
controller: textFieldController,
style: TextStyle(
fontSize: 24,
color: Colors.black,
),
),
),
RaisedButton(
child: Text(
'Go to second screen',
style: TextStyle(fontSize: 24),
),
onPressed: () {
_sendDataToSecondScreen(context);
},
)
],
),
);
}
// get the text in the TextField and start the Second Screen
void _sendDataToSecondScreen(BuildContext context) {
String textToSend = textFieldController.text;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen(text: textToSend,),
));
}
}
class SecondScreen extends StatelessWidget {
final String text;
// receive data from the FirstScreen as a parameter
SecondScreen({Key key, @required this.text}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Second screen')),
body: Center(
child: Text(
text,
style: TextStyle(fontSize: 24),
),
),
);
}
}
Pasar datos a la pantalla anterior
Al devolver datos, debe hacer lo siguiente:
En
FirstScreen
, useNavigator
para presionar (iniciar)SecondScreen
unasync
método y esperar el resultado que devolverá cuando finalice.final result = await Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(), ));
En
SecondScreen
, incluya los datos que desea pasar como parámetro cuando abra el archivoNavigator
.Navigator.pop(context, 'Hello');
Luego
FirstScreen
terminaráawait
y podrás usar el resultado.setState(() { text = result; });
Aquí está el código completo main.dart
para su referencia.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Flutter',
home: FirstScreen(),
));
}
class FirstScreen extends StatefulWidget {
@override
_FirstScreenState createState() {
return _FirstScreenState();
}
}
class _FirstScreenState extends State<FirstScreen> {
String text = 'Text';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('First screen')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(32.0),
child: Text(
text,
style: TextStyle(fontSize: 24),
),
),
RaisedButton(
child: Text(
'Go to second screen',
style: TextStyle(fontSize: 24),
),
onPressed: () {
_awaitReturnValueFromSecondScreen(context);
},
)
],
),
),
);
}
void _awaitReturnValueFromSecondScreen(BuildContext context) async {
// start the SecondScreen and wait for it to finish with a result
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen(),
));
// after the SecondScreen result comes back update the Text widget with it
setState(() {
text = result;
});
}
}
class SecondScreen extends StatefulWidget {
@override
_SecondScreenState createState() {
return _SecondScreenState();
}
}
class _SecondScreenState extends State<SecondScreen> {
// this allows us to access the TextField text
TextEditingController textFieldController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Second screen')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(32.0),
child: TextField(
controller: textFieldController,
style: TextStyle(
fontSize: 24,
color: Colors.black,
),
),
),
RaisedButton(
child: Text(
'Send text back',
style: TextStyle(fontSize: 24),
),
onPressed: () {
_sendDataBack(context);
},
)
],
),
);
}
// get the text in the TextField and send it back to the FirstScreen
void _sendDataBack(BuildContext context) {
String textToSendBack = textFieldController.text;
Navigator.pop(context, textToSendBack);
}
}
Esta solución es muy fácil pasando variables en el constructor:
primera página:
Navigator.of(context).push(MaterialPageRoute(builder:(context)=>SecondPage('something')));
segunda pagina:
class SecondPage extends StatefulWidget {
String something;
SecondPage(this.something);
@override
State<StatefulWidget> createState() {
return SecondPageState(this.something);
}
}
class SecondPageState extends State<SecondPage> {
String something;
SecondPageState(this.something);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//now you have passing variable
title: Text(something),
),
...
}
Obtenga la solución perfecta:
Desde la primera pantalla navegue a otras como:
Navigator.pushNamed(context, "second",arguments: {"name" : "Bijendra", "rollNo": 65210}); },
En la segunda pantalla del método de compilación, obtenga lo siguiente:
@override Widget build(BuildContext context) { final Map<String, Object>rcvdData = ModalRoute.of(context).settings.arguments; print("rcvd fdata ${rcvdData['name']}"); print("rcvd fdata ${rcvdData}"); return Scaffold(appBar: AppBar(title: Text("Second")), body: Container(child: Column(children: <Widget>[ Text("Second"), ],),),); }
La manera más fácil
Primera página.dart
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PasswordRoute(usernameController)));
//usernameController es un valor de cadena, si desea pasar varios valores, agregue todos
SegundaPágina.dart
class PasswordRoute extends StatefulWidget {
final String usernameController;//if you have multiple values add here
PasswordRoute(this.usernameController, {Key key}): super(key: key);//add also..example this.abc,this...
@override
State<StatefulWidget> createState() => _PasswordPageState();
}
class _PasswordPageState extends State<PasswordRoute> {
@override
Widget build(BuildContext context) {
...child: Text(widget.usernameController);
}
}
Las respuestas anteriores son útiles para una aplicación pequeña, pero si desea eliminar el dolor de cabeza de preocuparse continuamente por el estado de los widgets, Google presentó el paquete Proveedor. https://pub.dev/packages/provider
Échale un vistazo o mira estos videos de Andrea Bizzotto: https://www.youtube.com/watch?v=MkFjtCov62g // Proveedor: La guía esencial https://www.youtube.com/watch?v =O71rYKcxUgA&t=258s // Proveedor: Introducción
Aprenda a utilizar el paquete Proveedor y estará listo para toda la vida :)