美文网首页
Flutter新版Navigator2.0基本用法

Flutter新版Navigator2.0基本用法

作者: xmb | 来源:发表于2021-06-28 18:30 被阅读0次
  • Navigator2.0特性:
  1. 支持自定义页面的路由栈
  2. 支持一次打开或关闭多个页面
  3. 支持删除当前页面下的页面
  4. 提供了解析web url路由的功能
  • 主要的几个概念:
  1. Page:用来表示路由栈中各个页面的不可变对象,Page是个抽象类,通常使用它的派生类MaterialPageCupertinoPage
  2. Router:配置Navigator。
  3. RouteDelegate:定义路由行为,监听RouteInformationParser和应用状态,并构建Pages
  4. 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作为MaterialApphome

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

WX20210628-182117@2x.png

相关文章

网友评论

      本文标题:Flutter新版Navigator2.0基本用法

      本文链接:https://www.haomeiwen.com/subject/kzfcultx.html