Navigator2.0
特性:
- 支持自定义页面的路由栈
- 支持一次打开或关闭多个页面
- 支持删除当前页面下的页面
- 提供了解析
web url
路由的功能
- 主要的几个概念:
Page
:用来表示路由栈中各个页面的不可变对象,Page
是个抽象类,通常使用它的派生类MaterialPage
或CupertinoPage
。Router
:配置Navigator。RouteDelegate
:定义路由行为,监听RouteInformationParser
和应用状态,并构建Pages
。RouteInformationParser
:应用在web端,移动端可缺省。
image.png
/** * 启动app之后路由调用: * 1. App启动先进入routeInformationParser * 2. 调用parser里面的parseRouteInformation方法,返回自定义的BiliRoutePath * 3. BiliRouteDelegate会被调用,调用BiliRouteDelegate的build方法 * 4. build方法里有定义路由堆栈pages,路由堆栈里有所有要显示的页面,可以对多个页面进行操作(新版导航的特性:可以指定显示哪一个,移除哪一个,添加页面,移除很多页面等操作) * 5. 然后会调用setNewRoutePath,重新调用build * 6. 打开新页面,调用build,使用新的路由堆栈 * */
1、自定义路由数据BiliRoutePath
/// 自定义路由数据,path class BiliRoutePath { final String? location; BiliRoutePath.home() : location = '/'; BiliRoutePath.detail() : location = '/detail'; }
2、定义RouteInformationParser
/// 可缺省,主要用于web,持有RouteInformationProvider 提供的 RouteInformation,可以将其解析为我们定义的数据类型 class BiliRouteInformationParser extends RouteInformationParser<BiliRoutePath> { @override Future<BiliRoutePath> parseRouteInformation(RouteInformation routeInformation) async { LogUtil.log('路由跟踪', 'parseRouteInformation'); // 字符串转为uri final uri = Uri.parse(routeInformation.location!); LogUtil.log('web uri', uri); if (uri.pathSegments.length == 0) { return BiliRoutePath.home(); } else { return BiliRoutePath.detail(); } } }
3、创建路由代理RouterDelegate
/// 路由代理 /// ChangeNotifier: 通过notifyListeners()修改路由状态 /// PopNavigatorRouterDelegateMixin: 可以复用popRoute方法 class BiliRouteDelegate extends RouterDelegate<BiliRoutePath> with ChangeNotifier, PopNavigatorRouterDelegateMixin { final GlobalKey<NavigatorState>? navigatorKey; /// 可以通过navigatorKey获取NavigatorState,来调用NavigatorState的方法 BiliRouteDelegate() : navigatorKey = GlobalKey<NavigatorState>(); List<MaterialPage> pages = []; DetailModel? detailModel; BiliRoutePath? path; @override Widget build(BuildContext context) { LogUtil.log('路由跟踪', 'build'); // 构建路由堆栈 pages = [ wrapPage(HomePage( onJumpDetail: (model) { this.detailModel = model; notifyListeners(); }, )), if (this.detailModel != null) wrapPage(DetailPage(detailModel: this.detailModel)) ]; return Navigator( key: navigatorKey, // 自己定义路由堆栈 pages: pages, /** * onPopPage: 可以控制是否可以返回 * */ onPopPage: (route, result) { // 控制是否可以返回 false-不能返回 true-可以返回 if (!route.didPop(result)) { return false; } return true; }, ); } @override Future<void> setNewRoutePath(BiliRoutePath path) async { this.path = path; LogUtil.log('路由跟踪', 'setNewRoutePath'); } // 定义构造方法,在构造方法中进行初始化 // @override // GlobalKey<NavigatorState>? get navigatorKey => throw UnimplementedError(); // 通过with PopNavigatorRouterDelegateMixin来实现 // @override // Future<bool> popRoute() { // throw UnimplementedError(); // } }
4、定义Router
作为MaterialApp
的home
void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { BiliRouteDelegate _routeDelegate = BiliRouteDelegate(); BiliRouteInformationParser _routeInformationParser = BiliRouteInformationParser(); @override void initState() { super.initState(); // 本地缓存预初始化 HiCache.preInit(); } @override Widget build(BuildContext context) { // 定义route var widget = Router( routerDelegate: _routeDelegate, routeInformationParser: _routeInformationParser, /// 当routeInformationParser不为空时,需要设置routeInformationProvider routeInformationProvider: PlatformRouteInformationProvider( initialRouteInformation: RouteInformation(location: '/'), ), ); return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: R.white, ), debugShowCheckedModeBanner: false, home: widget, ); } }
其他用到的页面代码:
HomePage
import 'package:flutter/material.dart'; import 'package:flutter_bilibili/model/deital_model.dart'; import 'package:flutter_bilibili/widget/app_bar.dart'; class HomePage extends StatefulWidget { const HomePage({Key? key, required this.onJumpDetail}) : super(key: key); final ValueChanged<DetailModel> onJumpDetail; @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: appBar('首页'), body: Container( child: Column( children: [ Text('首页内容'), MaterialButton( onPressed: () => widget.onJumpDetail(DetailModel(detailId: '1111')), child: Text('进入详情'), ), ], ), ), ); } } DetailPage
import 'package:flutter/material.dart'; import 'package:flutter_bilibili/model/deital_model.dart'; import 'package:flutter_bilibili/widget/app_bar.dart'; class DetailPage extends StatefulWidget { const DetailPage({Key? key, this.detailModel}) : super(key: key); final DetailModel? detailModel; @override _DetailPageState createState() => _DetailPageState(); } class _DetailPageState extends State<DetailPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: appBar('详情页'), body: Container( child: Text('详情页内容 - ${widget.detailModel?.detailId}'), ), ); } }