在flutter中 route是一个绕不开,必须面对,且很经常使用东西bash
Route就是路由,顾名思义,负责你页面间的跳转async
不想看代码和思路分析的直接copy了拿去用就行 没有啥外部依赖,只须要注意_rootRoute 后面的字符串须要和initialRoute 对应便可工具
路由又分静态和动态路由ui
静态就是不须要传参数的,这样的路由能够直接定义在MaterialApp/WidgetsApp 里 这样能够经过Navigator.pushNamed
调用spa
动态的就是传入一个PageRoute
, 一般是一个MaterialPageRoute
或者CupertinoPageRoute
,或者你若是有自定义的有可使用3d
这里我使用一个个人工具类来实现跳转,由于大部分状况下,工程中的路由都是动态的,也就是须要传参数的,因此工具类中只包含了使用Widget相关的方案code
import 'dart:async';
import 'package:flutter/material.dart';
class RouteHelper {
static Future<T> pushWidget<T>(
BuildContext context,
Widget widget, {
bool replaceRoot = false,
bool replaceCurrent = false,
}) {
return pushRoute(
context,
MaterialPageRoute(builder: (ctx) => widget),
replaceRoot: replaceRoot,
replaceCurrent: replaceCurrent,
);
}
static Future<T> pushRoute<T>(
BuildContext context,
PageRoute<T> route, {
bool replaceRoot = false,
bool replaceCurrent = false,
}) {
assert(!(replaceRoot == true && replaceCurrent == true));
if (replaceRoot == true) {
return Navigator.pushAndRemoveUntil(
context,
route,
_rootRoute,
);
}
if (replaceCurrent == true) {
return Navigator.pushReplacement(context, route);
}
return Navigator.push(context, route);
}
}
var _rootRoute = ModalRoute.withName("home");
复制代码
解析一下这个类,有两个方法,一个是接受PageRoute,一个是接收Widgetcdn
接收Widget的是讲Widget包装为MaterialPageRoute,而后传给另外一个方法对象
另外一个方法中包含3种状况,一种是替换根节点,一种是替换当前页面(关闭当前,且开启新页面),还有一种就是日常的push(即 不关闭当前,直接开启新的)blog
根据传参不一样而有所不一样
有一个_rootRoute
变量,这个变量的目的是用于替换根节点,'home'
是我定义在MaterialApp
里的initialRoute
,这样一一对应才能确保替换根节点
固然这个类也能够继续扩展,好比将routes定义在内,而后传route name 参数,接着经过routes来提取出named对应的Widget/Route 接着传入pushRoute
方法进行跳转便可
这个简便的Helper还有另外一个好处,就是能够方便后续批量替换Route实现,好比有一天你想自定义一个PageRoute,不使用MaterialRoute ,那么你只须要替换以下如所示的部分便可
固然还能够有别的扩展方法来支持named
好比查看Navigator
的源码发现pushNamed
,就是经过widget.onGenerateRoute
方法获取到route
的,我这里直接在helper中写就行了
Helper 写完了,咱们看看使用的方法 使用起来也很简单
好比强登录应用
void _login() {
RouteHelper.pushWidget(context, HomeRootPage(), replaceRoot: true);
}
复制代码
这里登陆成功后,我直接替换了root节点,而后根路由就变成了主页面
void _forgetPwd() {
RouteHelper.pushWidget(context, ForgetPwdPage());
}
void _register() {
RouteHelper.pushWidget(context, RegiseterPage());
}
复制代码
忘记密码和注册都基于登陆在作,最终要返回登陆,因此这里用普通的调用方法
_register() {
RouteHelper.pushWidget(
context,
RegisterSuccessPage(),
replaceCurrent: true,
);
}
复制代码
注册成功后我这里有一个单独的注册成功页,写了一些注册后的注意事项,而返回又应该直接返回到登陆页面,因此这里我须要替换掉当前的页面,只用replaceCurrent 便可
固然方法接受返回值也是容许的
_orderDetail(String item) async {
//todo 查看订单详情
var result = await RouteHelper.pushWidget<bool>(context, OrderDetailPage(id: item));
if (result == true) {
_refresh();
}
}
复制代码
这里若是在详情页买了东西/加到购物车,回到主页面,是要刷新页面的,因此咱们接收返回值,而后判断
小tips:这里之因此用result == true 而不是 if(result) 是由于dart中 bool
是有3个值的 true false null if(result==true)
能够将result 为 null的状况规避掉,提高代码健壮性,这个不得不说是dart 彻底面向对象形成的反作用