передача данных между экранами
На главном экране я ввожу в поле ввода текст, нажимаю на кнопку, происходит переход на второй экран, происходит передача данных и отображение на втором экране.
Когда я все делаю то же самое но на втором экране, при переходе на первый экран, данные не переносятся.
Первый способ
Navigator.pop(context, _MyHomePageState(data: _controller.text));
Второй способ
Navigator.push(
context,
//MaterialPageRoute(builder: (context) => Two())
MaterialPageRoute(builder: (_) => _MyHomePageState(data: _controller.text,))
).then((value) {
_controller.text = ''; //очистка поля ввода
});
Ошибка в
_MyHomePageState(data: _controller.text,)
Далее, полный код и скриншоты
main.dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Name App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState(data: null);
}
class _MyHomePageState extends State<MyHomePage> {
//это будет передаваться в другой экран
TextEditingController _controller;
//это будет передано с другого экрана
String data;
_MyHomePageState ({@required this.data});
@override
void initState() {
super.initState();
_controller = TextEditingController();
data = '';
}
@override
void dispose() {
super.dispose();
}
void _f1() {
setState(() {
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main screen'),
),
body: Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: _controller,
cursorColor: Colors.pink,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide()
),
),
),
),
),
Align(
alignment: Alignment.center,
child: Text(
(data == null) ? '' : data,
style: TextStyle(
fontSize: 46.0,
color: Colors.pink
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
margin: const EdgeInsets.all(16.0),
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
//MaterialPageRoute(builder: (context) => Two())
MaterialPageRoute(builder: (_) => Two(data: _controller.text,))
).then((value) {
_controller.text = ''; //очистка поля ввода
});
},
splashColor: Colors.blue.withOpacity(0.5),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
child: Text(
'Go to Two',
style: TextStyle(
color: Colors.deepPurple,
fontSize: 20.0,
),
),
),
),
),
],
),
);
}
}
class Two extends StatelessWidget {
//это будет передаваться в другой экран
TextEditingController _controller = TextEditingController();
//это будет передаваться в другой экран
String data;
Two({Key key, @required this.data}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Two screen'),
),
body: Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: _controller,
cursorColor: Colors.pink,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide()
),
),
),
),
),
Align(
alignment: Alignment.center,
child: Text(
(data == null) ? '' : data,
style: TextStyle(
fontSize: 46.0,
color: Colors.blue
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
margin: const EdgeInsets.all(16.0),
child: RaisedButton(
onPressed: () {
//1 способ ошибки нет, но данные не выводятся
Navigator.pop(context, _MyHomePageState(data: _controller.text));
//2 способ ошибка в _MyHomePageState(data: _controller.text,)
/*Navigator.push(
context,
//MaterialPageRoute(builder: (context) => Two())
MaterialPageRoute(builder: (_) => _MyHomePageState(data: _controller.text,))
).then((value) {
_controller.text = ''; //очистка поля ввода
});*/
},
splashColor: Colors.blue.withOpacity(0.5),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
child: Text(
'Go to Main',
style: TextStyle(
color: Colors.deepPurple,
fontSize: 20.0,
),
),
),
),
),
],
),
);
}
}
Ответы (1 шт):
Вызов конструктора _MyHomePageState должен выполняться только один раз, при создании виджета _MyHomePage, все остальные вызовы не имеют смысла, т.к. новые экземпляры просто повисают в воздухе. Параметр data из конструктора удалил - для корневого виджета он бесполезен.
При возврате со второй страницы на первую передавайте только сами данные, в данном случае это содержимое _controller.text. Если нужно вернуть сразу несколько значений, то можно создать свой класс и возвращать его экземпляр, но в более-менее серьезных проектах стоит воспользоваться глобальным хранилищем состояния, например BLOC.
Сама обработка полученного со второй страницы значения должна сопровождаться вызовом setState, иначе главная страница будет отображать старые данные.
Вот основные изменения вашего кода в diff-формате:
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -18,7 +18,7 @@ class MyApp extends StatelessWidget {
class MyHomePage extends StatefulWidget {
@override
- _MyHomePageState createState() => _MyHomePageState(data: null);
+ _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@@ -28,8 +28,6 @@ class _MyHomePageState extends State<MyHomePage> {
//это будет передано с другого экрана
String data;
- _MyHomePageState({@required this.data});
-
@override
void initState() {
super.initState();
@@ -91,6 +89,9 @@ class _MyHomePageState extends State<MyHomePage> {
data: _controller.text,
))).then((value) {
_controller.text = ''; //очистка поля ввода
+ setState(() {
+ data = value;
+ });
});
},
splashColor: Colors.blue.withOpacity(0.5),
@@ -113,10 +114,10 @@ class _MyHomePageState extends State<MyHomePage> {
class Two extends StatelessWidget {
//это будет передаваться в другой экран
- TextEditingController _controller = TextEditingController();
+ final TextEditingController _controller = TextEditingController();
//это будет передаваться в другой экран
- String data;
+ final String data;
Two({Key key, @required this.data}) : super(key: key);
@@ -157,7 +158,7 @@ class Two extends StatelessWidget {
child: RaisedButton(
onPressed: () {
//1 способ ошибки нет, но данные не выводятся
- Navigator.pop(context, _MyHomePageState(data: _controller.text));
+ Navigator.pop(context, _controller.text);
--



