Flutter路由传递参数及解析实现

作者:岛上码农 时间:2023-06-22 11:48:45 

在实际开发中,我们经常会需要在页面跳转的时候携带路由参数,典型的例子就是从列表到详情页的时候,需要携带详情的 id,以便详情页获取对应的数据。同时,有些时候还需要返回时携带参数返回上一级,以便上级页面根据返回结果更新。本篇将介绍这两种情形的实现。

Navigator 的 push 和 pop方法

Navigator 导航器的 pushpop 方法可以携带参数在页面间传递,其他变形的方法也一样。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 回传到上级页面。

代码实现

我们使用一个列表跳转到详情页来演示路由参数获取(列表构建文章请看Flutter 入门与实战(五):来一个图文并茂的列表)。点击列表行时携带列表数据项的 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就是我们上一篇路由拦截中的onGenerateRoutesettings 参数,因此假设我们需要增加额外的路由参数(例如全局参数),则可以在 onGenerateRoute 方法中重新组装路由参数。

这里有个地方需要注意,因为返回时要携带参数,因此我们需要拦截返回响应事件,这时候整个组件可以使用 WillPopScope 包裹,该方法带有两个参数:

  • child:子组件,即原有的页面组件;

  • onWillPop:返回前拦截处理,返回一个Future<bool>对象,若为 false,则不会返回。若为 true,则返回上一级。这里我们调用了 携带参数的 pop 方法以便将参数回传。实际这里往往做一些其他处理,例如表单没有保存时询问是否确认离开,还有广大电商的活动页询问你是“忍痛离开”或是“再看一会”的处理。

最终效果

最终运行效果如下图所示,详情页获取到了 id 参数,返回的时候也接收到了对应的 id

Flutter路由传递参数及解析实现

路由参数拦截

路由参数可以通过 onGenerateRoute拦截进行额外处理,示例代码如下。需要注意,这里仅仅是示例,由于 settingsarguments 可能为任意类型,因此可能会导致转换失败。实际业务中最好是约定路由参数传递类型,避免参数形式不统一导致异常出现。

static Route onGenerateRoute<T extends Object>(RouteSettings settings) {
 var arguments = settings.arguments as Map<String, dynamic>;
 if (arguments != null) {
   arguments['event'] = '路由拦截增加的参数';
 }
 RouteSettings newSettings =
     settings.copyWith(name: settings.name, arguments: arguments);
return CupertinoPageRoute<T>(
   settings: newSettings,
   builder: (context) {
     String name = settings.name;
     if (routeTables[name] == null) {
       name = notFoundPath;
     }
Widget widget = routeTables[name](context);
return widget;
   },
 );
}

来源:https://blog.csdn.net/shuijian00/article/details/121579110

标签:Flutter,路由,解析
0
投稿

猜你喜欢

  • Springboot Thymeleaf模板文件调用Java类静态方法

    2023-11-25 05:34:47
  • Android编程之canvas绘制各种图形(点,直线,弧,圆,椭圆,文字,矩形,多边形,曲线,圆角矩形)

    2023-10-16 12:16:14
  • 在maven工程里运行java main方法

    2023-09-18 04:33:20
  • Android使用自定义View实现360手机卫士波浪球进度的效果

    2023-03-21 19:18:34
  • android JSON解析数据 android解析天气预报

    2022-01-16 03:33:53
  • android studio 新建项目报错的解决之路

    2022-09-20 14:24:58
  • java明文密码三重加密方法

    2022-09-01 05:59:26
  • 修改Android FloatingActionButton的title的文字颜色及背景颜色实例详解

    2021-08-21 21:18:44
  • 浅谈Java代码的 微信长链转短链接口使用 post 请求封装Json(实例)

    2023-07-27 19:36:09
  • 详解Spring Boot微服务如何集成fescar解决分布式事务问题

    2022-01-21 18:43:51
  • android照相、相册获取图片剪裁报错的解决方法

    2021-11-21 20:18:14
  • WinForm实现仿视频播放器左下角滚动新闻效果的方法

    2021-11-04 19:43:41
  • SpringBoot中如何统一接口返回与全局异常处理详解

    2021-08-11 02:22:35
  • Spring Boot创建非可执行jar包的实例教程

    2022-10-05 12:47:35
  • 解析MapStruct转换javaBean时出现的诡异事件

    2022-05-15 01:16:28
  • 浅析C#中文件路径的操作

    2023-11-09 16:24:30
  • Android连接指定Wifi的方法实例代码

    2022-03-01 06:26:25
  • Jetpack Compose自定义动画与Animatable详解

    2021-07-04 20:26:08
  • 零基础学Java:Java开发工具 Eclipse 安装过程创建第一个Java项目及Eclipse的一些基础使用技巧

    2022-09-05 03:46:03
  • SpringBoot使用AOP与注解实现请求参数自动填充流程详解

    2022-08-18 17:30:36
  • asp之家 软件编程 m.aspxhome.com