当前位置:   article > 正文

flutter 一个简单的Route Helper/Navigator Helper

flutter navigator 换根节点

flutter中 route是一个绕不开,必须面对,且很常用东西

Route就是路由,顾名思义,负责你页面间的跳转

不想看代码和思路分析的直接copy了拿去用就行 没有啥外部依赖,只需要注意_rootRoute 后面的字符串需要和initialRoute 对应即可

路由又分静态和动态路由

静态就是不需要传参数的,这样的路由可以直接定义在MaterialApp/WidgetsApp 里 这样可以通过Navigator.pushNamed调用

动态的就是传入一个PageRoute, 通常是一个MaterialPageRoute 或者CupertinoPageRoute,或者你如果有自定义的有可以使用

这里我使用一个我的工具类来实现跳转,因为大部分情况下,工程中的路由都是动态的,也就是需要传参数的,所以工具类中只包含了使用Widget相关的方案

  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. class RouteHelper {
  4. static Future<T> pushWidget<T>(
  5. BuildContext context,
  6. Widget widget, {
  7. bool replaceRoot = false,
  8. bool replaceCurrent = false,
  9. }) {
  10. return pushRoute(
  11. context,
  12. MaterialPageRoute(builder: (ctx) => widget),
  13. replaceRoot: replaceRoot,
  14. replaceCurrent: replaceCurrent,
  15. );
  16. }
  17. static Future<T> pushRoute<T>(
  18. BuildContext context,
  19. PageRoute<T> route, {
  20. bool replaceRoot = false,
  21. bool replaceCurrent = false,
  22. }) {
  23. assert(!(replaceRoot == true && replaceCurrent == true));
  24. if (replaceRoot == true) {
  25. return Navigator.pushAndRemoveUntil(
  26. context,
  27. route,
  28. _rootRoute,
  29. );
  30. }
  31. if (replaceCurrent == true) {
  32. return Navigator.pushReplacement(context, route);
  33. }
  34. return Navigator.push(context, route);
  35. }
  36. }
  37. var _rootRoute = ModalRoute.withName("home");
  38. 复制代码

解析一下这个类,有两个方法,一个是接受PageRoute,一个是接收Widget

接收Widget的是讲Widget包装为MaterialPageRoute,然后传给另一个方法

另一个方法中包含3种情况,一种是替换根节点,一种是替换当前页面(关闭当前,且开启新页面),还有一种就是平常的push(即 不关闭当前,直接开启新的)

根据传参不同而有所不同

有一个_rootRoute变量,这个变量的目的是用于替换根节点,'home'是我定义在MaterialApp里的initialRoute,这样一一对应才能确保替换根节点


当然这个类也可以继续扩展,比如将routes定义在内,然后传route name 参数,接着通过routes来提取出named对应的Widget/Route 接着传入pushRoute方法进行跳转即可


这个简便的Helper还有另一个好处,就是可以方便后续批量替换Route实现,比如有一天你想自定义一个PageRoute,不使用MaterialRoute ,那么你只需要替换如下如所示的部分即可


当然还可以有别的扩展方法来支持named 比如查看Navigator的源码发现pushNamed,就是通过widget.onGenerateRoute方法获取到route的,我这里直接在helper中写就好了


Helper 写完了,我们看看使用的方法 使用起来也很简单

比如强登陆应用

  1. void _login() {
  2. RouteHelper.pushWidget(context, HomeRootPage(), replaceRoot: true);
  3. }
  4. 复制代码

这里登录成功后,我直接替换了root节点,然后根路由就变成了主页面

  1. void _forgetPwd() {
  2. RouteHelper.pushWidget(context, ForgetPwdPage());
  3. }
  4. void _register() {
  5. RouteHelper.pushWidget(context, RegiseterPage());
  6. }
  7. 复制代码

忘记密码和注册都基于登录在做,最终要返回登录,所以这里用普通的调用方法

  1. _register() {
  2. RouteHelper.pushWidget(
  3. context,
  4. RegisterSuccessPage(),
  5. replaceCurrent: true,
  6. );
  7. }
  8. 复制代码

注册成功后我这里有一个单独的注册成功页,写了一些注册后的注意事项,而返回又应该直接返回到登录页面,所以这里我需要替换掉当前的页面,只用replaceCurrent 即可


当然方法接受返回值也是允许的

  1. _orderDetail(String item) async {
  2. //todo 查看订单详情
  3. var result = await RouteHelper.pushWidget<bool>(context, OrderDetailPage(id: item));
  4. if (result == true) {
  5. _refresh();
  6. }
  7. }
  8. 复制代码

这里如果在详情页买了东西/加到购物车,回到主页面,是要刷新页面的,所以我们接收返回值,然后判断

小tips:这里之所以用result == true 而不是 if(result) 是因为dart中 bool是有3个值的 true false null if(result==true) 可以将result 为 null的情况规避掉,提升代码健壮性,这个不得不说是dart 完全面向对象造成的副作用


声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号