阅读 1672

对Flutter路由管理库Fluro的封装

在公司使用flutter开发过一个app后,我也算一个老用户了,练习时长半年,最近公司的搞重构,要用到fluro来对路由进行管理,我们一起来简单体验下。

1.增加page_router.dart文件

在这里文件里面编写下面的代码

一个PageRouter类,里面我们定义静态的fluro提供的Router实例 然后再定义个静态方法setupRoutes,用来设置我们的routes

2.增加page_routes.dart

在这里我定义了一个map集合,key是页面的path,value是按照fluro的要求是一个Handler的实例

这里注意到我们的HomePage页面需要传入一个userId参数,那我在这里就要提前把它传入进去 首先我在定义path时要注意/home是页面的path,:userId相当于页面url的参数,是个占位符,一会跳转的时候我们要传入 比如:router.navigateTo(context, "/home/1234", transition: TransitionType.fadeIn); 另外那个params参数是个map,key就是我们左边定义的占位符的参数名字,但是呢,params["userId"]是个List,并没有直接取出传的值,我不太明白这里为啥搞个List出来,直接给我值不行吗?而且这个值实在List的第一个,所以我们用.first取出来

3.注册routes

上面我们定义好了routes,但是还没有跟fluro扯上半点关系,接下来我们把它们关联起来

回到page_router.dart文件 我们在setupRoutes方法里面添加代码,我们先导入page_routes.dart文件

在setupRoutes里面我们遍历那个map,里面调用router.define()来把路由注册到Fluro Router。 这里我们已经完成了大部分的工作 强调一下,在我使用fluro之前我也搜索了相关文章,发现他们在注册路由时都是在手动注册,就是类似这样的代码

router.define(xx, handler: xxHandler);
router.define(xx, handler: xxHandler);
复制代码

作为程序员能自动就别手动对吧,这样的重复代码直接循环搞定就行了,也可能别人是为了演示简单写写吧。

4.设置router到MaterialApp

  • 先在main.dart的入口main()方法里面执行下面的代码
  PageRouter.setupRoutes();
复制代码

就是调用上面PageRouter的setupRoutes方法执行注册routes

  • 跟MaterialApp绑定
 MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
primarySwatch: Colors.blue,
 ),
 onGenerateRoute: PageRouter.router.generator,
) 

复制代码

5.改进

我们回顾下第2步添加routes的时候的写法 我感觉看起来还是不够优雅啊

  • 都是以字符串来命名路由名字,很容易起冲突导致被覆盖,当页面名字多的时候后面添加的页面path容易跟上面的一样,而且我们页面传的参数那个占位符写起来样子怪怪的,两三个参数下来path长长的一大堆,
  • 页面传参数很啰嗦,我觉得那个params设计的很不好,是个map我们取值时类型丢失,我们一眼看过去不知道到底取得什么类型,虽然params取出来的是个List,我们可以知道是个String,但是我无法从肉眼直接看到是什么类型,特别是当接盘侠来改代码时,一脸懵逼啊。类型丢失就是因为fluro内部写死了从params取出来的都是String的值,不过可以理解,一般url传参数也都是字符串类型吧,但是比如我上面给ClassDetailPage传id时,因为我定义的是int类型,而我通过params["id"][0]拿到的是String,我还要做个类型转换,
  • 这串代码整体看起来冗余,写起来很麻烦

废话说太多了,来优化一下吧 首先解决页面之间传值得问题,用fluro传值需要在定义routes的地方提前写好,我认为不太符合习惯,我的习惯是我在跳转页面的时候我再去组合数组把值传过去,现在我不仅要在定义routes的时候取值赋值,还要在跳页面的时候再组合数据进行传值, 这时候呢,如果你是安卓程序员你会不会想到Activity之间传值得时候用到的一个叫Bundle的东西呢?没错,我们把它搞过来

我们使用这个有几个好处

  • 一眼看过去能明显知道你要从map中取得是什么类型的值,获取你放的是什么类型的值
  • 我们把页面之间要传递的数据通过一个Bundle对象打包传输,避免了我们在使用fluro时挨个从params来取参数,
  • 如果你用的key不小心写错了,我会抛出异常提示,不用等到用的时候才发现是null,

看下使用效果

这样子做,接盘侠再也不会抱怨不知道你写的什么类型了,上面我写错了类型,ide也能提示出来

接下来我们改造下fluro给页面传参数那里 增加一个类

一个叫PageBuilder的类,getHandler最终返回fluro需要的handler,

下面我们来改造page_routes.dart文件

看这里是不是比之前清爽了很多,

  • map的key不再是字符串,我们定义了一个枚举,PageName,我们知道枚举的值不能重复,当你写重复的时候,ide直接提示出来了,这样保证了我们不会出现像字符串那样重复
  • 我们看下map的value,是不是很清爽,没有了之前那一大堆的东西,看下之前的

现在看的话感觉这就是坨~~~啊

优化后我们每次增加页面只需要先增加一个页面名称到枚举PageName,然后再来给这个map添加key和value vlaue就直接写

PageBuilder(builder: (bundle) => LoginPage())
复制代码

这里这个bundle就是你在页面之间传值得bundle,你要把要传输的值放在这个bundle对象里面,然后手动传到页面的参数里比如这个 PageBuilder(builder: (bundle) => HomePage(bundle)) HomePage里面我声明了final Bundle bundle;

来看下我们怎么传值

这里我们要用到flutter自带的Navigator来跳转了,Navigator.pushNamed的第二个参数是String类型,所以我们这里对这个枚举的值进行toString一下,可以看到我们这里直接从PageName来拿页面名字,而不用像之前那样自己输入字符串,很容易输入错误, 再看arguments,这个参数就放我们的bundle对象,通过这个参数把bundle传输到下一个页面

最后

在这里感谢fluro作者的贡献,大家有什么想法可以评论留言哦,祝大家中秋节快乐!

关注下面的标签,发现更多相似文章
评论