页面传值
在 Android 当中,我们通过 Intent 携带数据进行 Activity 之间的数据传递,在 Flutter 中,根据 Route 的构建方式的不同传值方式也分为两种。
使用构造方法
为目标 Route 创建一个带参的构造函数,跳转时,参数携带要传递的数据:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
routes: {
"/": (BuildContext context) => HomeRoute(),
},
));
}
class HomeRoute extends StatelessWidget {
final userNameController = TextEditingController();
final passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: "输入用户名",
),
controller: userNameController,
),
TextField(
decoration: InputDecoration(
hintText: "输入密碼",
),
obscureText: true, //是否是密码
controller: passwordController,
),
MaterialButton(
onPressed: () {
//根据输入内容创建要传递的数据对象
Person person =
Person(userNameController.text, passwordController.text);
//跳转,并将 person 作为参数传入目标 Route
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => SecondRoute(person),
));
},
minWidth: double.infinity,
child: Text("提交"),
color: Colors.cyan,
),
],
),
),
);
}
}
class SecondRoute extends StatelessWidget {
final Person person;
SecondRoute(this.person);
@override
Widget build(BuildContext context) {
String message;
if (person.username == "tom" && person.password == "123") {
message = "欢迎光临,tom";
} else {
message = "密码或用户名有错";
}
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: Text(message),
),
);
}
}
///数据对象
class Person {
String username;
String password;
Person(this.username, this.password);
}
在上面的例子中,在转跳时,我们将需要传递的数据作为构造函数的参数传入,达到了传值的目的。
不使用构造方法
在上面的例子中,我们使用目标 Route 的带参构造函数来达成传值的目的,Flutter 其实还提供了更加“优雅”的传值方式,其实我也不觉得哪里优雅了,但好多文章说优雅,那就优雅吧。。。
那就是使用 RouteSettings 来进行值传递,对于构造 Route 来说,MaterialPageRoute
有一个 settings
参数,它是一个 RouteSettings
类型的对象,可以帮助我们在 Route 之间进行数值传递,使用方法如下:
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => SecondRoute(), //指定目标 Route
settings: RouteSettings( //通过 RouteSettings 传递数据
arguments: person
),
));
对于目标 Route ,获取传递过来的值也非常简单,需要借助 ModalRoute.of()
方法可以帮助我们获取:
Person person = ModalRoute.of(context).settings.arguments;
对于命名 Route 的值传递,我们可以设置其 argument
参数进行值发送,然后通过上面的方法也一样可以获得上一个 Route 传递过来的值:
Navigator.pushNamed(context, "/SecondRoute", arguments: person);
回传数据
在 Android 中,我们使用 onActivityResult
来接收别的 Activity 回传过来的数据,在 Flutter 中,这一操作用到了异步,首先回传的页面同样是执行 pop 方法,只不过在参数中带上了需要回传的数据:
Navigator.pop(context, {"id": 11111, "name": "张三"});
在接收端需要用到异步来接受回传的数据。实际上,Navigator.push 方法的返回值就是一个 Future 对象,可以调用其 then
方法来获取传递过来的值:
var future = Navigator.pushNamed(context, "Second",arguments: {"id": 123123, "name": "张三"});
future.then((value) {
//因为回传过来的数据会被当成是 Object 类型的,所以将其转换为 dynamic 类型的,方便获取数据。
dynamic result = value;
print("${result['id']}" + result['name']);
});
也可以这样写:
onPressed: () {
buttonClick(context);
},
buttonClick(BuildContext context) async {
dynamic value = await Navigator.pushNamed(context, "Second",arguments: {"id": 123123, "name": "张三"});
print("${value['id']}" + value['name']);
}
有关 Futter 中的异步和 Future 的更多信息,请看这里 掘金 - 燃烧的鱼丸 - flutter实战5:异步async、await和Future的使用技巧