- 
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}'),
      ),
    );
  }
}











