Flutter路由——Navigator2.0

Navigator 2.0提供了一系列全新的接口,可以实现将路由状态成为应用状态的一部分,新增的API如下:

  • Page:用来表示Navigator路由栈中各个页面的不可变对象,Page是一个抽象类通常使用它的派生类:MaterialPage或CupertinoPage;
  • Router:用来配置要用Navigator展示的页面列表,通常该页面列表会根据系统或应用程序的状态改变而改变,除了直接使用Router本身外还可以使用MaterialApp.router()来创建Router;
  • RouterDelegate:定义应用程序中的路由行为,例如Router如何知道应用程序状态的变化以及如何响应,监听RouteInformationParser和应用状态,并使用当前列表来构建Pages;
  • RouteInformationParser:可缺省,主要应用于web,持有RouteInformationProvider提供的RouteInformation,可以将其解析为我们定义的数据类型;
  • BackButtonDispatcher:响应后退按钮,并通知Router;

上面的API中BackButtonDispatcher很少用到,对于移动端来说,只需要用到Page、Router和RouterDelegate这三个API即可。

RouterDelegate与Router、RouteInformationParser在一起的交互和应用程序的状态如下:
Flutter路由——Navigator2.0_第1张图片

  • 1.当系统打开一个新页面时,RouteInformationParser会将其转换为应用中的具体数据类型T;
  • 2.该数据类型会被传递给RouterDelegate的setNewRoutePath方法,我们可以在这里更新路由状态;
  • 3.notifyListeners会通知Router重建RouterDelegate;
  • 4.RouterDelegate.build()返回一个新的Navigator实例,并最终展示出打开的页面;

代码实例:

/// @description hu
import 'package:flutter/material.dart';
import 'package:up_china/model/video_model.dart';
import 'package:up_china/page/home_page.dart';
import 'package:up_china/page/video_detail_page.dart';

void main() {
  runApp(UPApp());
}

class UPApp extends StatefulWidget {
  
  State<StatefulWidget> createState() => _UPAppState();
}

class _UPAppState extends State<UPApp> {
  UPDelegate _routerDelegate = UPRouterDelegate();
  UPRouteInformationParser _routeInformationParser =
  UPRouteInformationParser();

  
  Widget build(BuildContext context) {
    print('_UPAppState:build');
    //定义route
    var widget = Router(
      routeInformationParser: _routeInformationParser,
      routerDelegate: _routerDelegate,

      ///routeInformationParser为null时可缺省,routeInformation提供者
      routeInformationProvider: PlatformRouteInformationProvider(
          initialRouteInformation: RouteInformation(location: '/')),
    );
    return MaterialApp(home: widget);
  }
}

class UPRouterDelegate extends RouterDelegate<UPRoutePath>
    with ChangeNotifier, PopNavigatorRouterDelegateMixin<UPRoutePath> {
  final GlobalKey<NavigatorState> navigatorKey;
  UPRoutePath path;
  List<MaterialPage> pages = [];
  VideoModel videoModel;

  //为Navigator设置一个key,必要的时候可以通过navigatorKey.currentState来获取到NavigatorState对象
  UPRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>();

  
  Widget build(BuildContext context) {
    //构建路由栈
    pages = [
      pageWrap(HomePage(
        onJumpToDetail: (mo) {
          this.videoModel = mo;
          notifyListeners();
        },
      )),
      if (videoModel != null)
        pageWrap(
          VideoDetailPage(videoModel),
        )
    ];
    print('UPRouterDelegate:build');
    return Navigator(
      key: navigatorKey,
      pages: pages,
      onPopPage: (route, result) {
        print('Navigator:onPopPage');
        //在这里可以控制是否可以返回
        if (!route.didPop(result)) {
          return false;
        }
        return true;
      },
    );
  }

  //路由初始化时,Router 会调用setNewRoutePath 方法来更新应用程序的路由状态:
  
  Future<void> setNewRoutePath(UPRoutePath path) async {
    print('UPRouterDelegate:setNewRoutePath:$path');
    this.path = path;
  }
}

///可缺省,主要应用与web,持有RouteInformationProvider 提供的 RouteInformation ,可以将其解析为我们定义的数据类型。
class UPRouteInformationParser extends RouteInformationParser<UPRoutePath> {
  
  Future<UPRoutePath> parseRouteInformation(
      RouteInformation routeInformation) async {
    final uri = Uri.parse(routeInformation.location);
    print('UPRouteInformationParser:parseRouteInformation:uri:$uri');
    if (uri.pathSegments.length == 0) {
      return UPRoutePath.home();
    }
    return UPRoutePath.detail();
  }
}

///定义路由path
class UPRoutePath {
  final String location;

  UPRoutePath.home() : location = "/";

  UPRoutePath.detail() : location = "/detail";
}

///创建Page
pageWrap(Widget child) {
  return MaterialPage(
    key: ValueKey(child.hashCode),
    child: child,
  );
}
  • APP启动:
    1.启动;
    2.RouteInformationParser:parseRouteInformation;
    3.RouterDelegate:build;
    4.RouterDelegate:setNewRoutePath;
    5.RouterDelegate:build;
  • 打开页面:RouterDelegate:build 返回一个新的Navigator实例,并展示新的页面;
  • 返回:Navigator:onPopPage;
    Flutter路由——Navigator2.0_第2张图片

你可能感兴趣的:(flutter)