-
Navigator2.0
特性:
- 支持自定义页面的路由栈
- 支持一次打开或关闭多个页面
- 支持删除当前页面下的页面
- 提供了解析
web url
路由的功能
- 主要的几个概念:
-
Page
:用来表示路由栈中各个页面的不可变对象,Page
是个抽象类,通常使用它的派生类MaterialPage
或CupertinoPage
。 -
Router
:配置Navigator。 -
RouteDelegate
:定义路由行为,监听RouteInformationParser
和应用状态,并构建Pages
。 -
RouteInformationParser
:应用在web端,移动端可缺省。

/**
* 启动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}'),
),
);
}
}

网友评论