Navigator 的 push 和 pop方法
Navigator 导航器的 push 和 pop 方法可以携带参数在页面间传递,其他变形的方法也一样。pushNamed 方法原型如下:
Future<T?> pushNamed<T extends Object?>(
String routeName, {
Object? arguments,
}) {
return push<T>(_routeNamed<T>(routeName, arguments: arguments)!);
}
除了 routeName 的命名路由以外,还有个可选参数 arguments 用于在路由页面传递参数。pop 方法也一样:
void pop<T extends Object?>([ T? result ]) {
//...
}
可以携带一个 result 回传到上级页面。
代码实现
我们使用一个列表跳转到详情页来演示路由参数获取(列表构建文章请看//www.jb51.net/article/213052.htm)。点击列表行时携带列表数据项的 id 跳转到详情页。从详情页返回时再把该 id 回传。列表项的 Widget 新增了一个 id属性,由构建列表时初始化得到。
class DynamicItem extends StatelessWidget {
final int id;
final String title;
final String imageUrl;
final int viewCount;
static const double ITEM_HEIGHT = 100;
static const double TITLE_HEIGHT = 80;
static const double MARGIN_SIZE = 10;
const DynamicItem(this.id, this.title, this.imageUrl, this.viewCount,
{Key key})
: super(key: key);
//...
}
列表的容器使用 GestureDetector 包裹,以便响应点击事件。 onTap 方法定义为一个 async 方法,以便使用 await 获取导航返回时的参数,并使用一个 SnackBar 显示返回的 id。这里 pushNamed 携带了一个 Map 对象将列表的 id传递到详情页。
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Container(
margin: EdgeInsets.all(MARGIN_SIZE),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_imageWrapper(this.imageUrl),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_titleWrapper(context, this.title),
_viewCountWrapper(this.viewCount.toString()),
],
),
)
],
),
),
onTap: () async {
Map<String, dynamic> routeParams = {'id': id};
var arguments = await Navigator.of(context)
.pushNamed(RouterTable.dynamicDetail, arguments: routeParams);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("从动态${(arguments as Map<String, dynamic>)['id']}返回"),
));
},
);
}
这里还使用了一个 arguments变量 接收导航返回的参数,导航若有返回参数,会返回一个 Future 对象,使用 await 即可接收。然后在使用 as 转换为实际的类型进行使用。 在详情页中,Flutter 提供了一个ModalRoute的类从当前上下文获取路由配置参数,代码如下所示:
class DynamicDetail extends StatelessWidget {
const DynamicDetail({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
Map<String, dynamic> routeParams =
ModalRoute.of(context).settings?.arguments;
return WillPopScope(
child: Scaffold(
appBar: AppBar(
title: Text('动态详情'),
brightness: Brightness.dark,
),
body: Center(
child: Text("产品 id: ${routeParams['id']}"),
),
),
onWillPop: () async {
Navigator.of(context).pop({'id': routeParams['id']});
return true;
},
);
}
}
实际上这个ModalRoute.of(context).settings就是我们上一篇路由拦截中的onGenerateRoute的 settings 参数,因此假设我们需要增加额外的路由参数(例如全局参数),则可以在 onGenerateRoute 方法中重新组装路由参数。 这里有个地方需要注意,因为返回时要携带参数,因此我们需要拦截返回响应事件,这时候整个组件可以使用 WillPopScope 包裹,该方法带有两个参数:
- child:子组件,即原有的页面组件;
- onWillPop:返回前拦截处理,返回一个 Future<bool>对象,若为 false,则不会返回。若为 true,则返回上一级。这里我们调用了 携带参数的 pop 方法以便将参数回传。实际这里往往做一些其他处理,例如表单没有保存询问是否确认李可,还有广大电商的活动页询问你是“忍痛离开”或是“再看一会”的处理。
最终效果
最终运行效果如下图所示,详情页获取到了 id 参数,返回的时候也接收到了对应的 id。
以上就是Flutter开发中的路由参数处理的详细内容,更多关于Flutter 路由参数处理的资料请关注编程网其它相关文章!