flutter Navigation 源码分析

Navigation 描述 管理一组具有堆栈规则的子小部件的小部件

许多应用程序在其小部件层次结构的顶部附近都有一个导航器,以便使用覆盖图显示其逻辑历史记录,最近访问的页面直观地位于旧页面的顶部。使用此模式可以让导航器通过在叠加层中四处移动小部件来从一个页面直观地过渡到另一个页面。类似地,导航器可用于通过将对话框小部件放置在当前页面上方来显示对话框

Overlay 描述 可以独立管理的条目堆栈

叠加让独立的子部件通过将它们插入叠加层的堆栈中,使视觉元素“漂浮”在其他部件之上。覆盖让这些小部件中的每一个都使用 对象管理​OverlayEntry​它们对覆盖的参与

routes

移动应用程序通常通过称为“屏幕”或“页面”的全屏元素显示其内容

入口 MaterialApp 文档描述

一个方便的小部件,它包装了许多 Material Design 应用程序通常需要的小部件

MaterialApp配置顶级Navigator以按以下顺序ca搜索路线:

  1. 对于/路由,使用home属性(如果非空)。

  2. 否则,如果路由表有路由条目,则使用路由表。

  3. 否则,如果提供,则调用onGenerateRoute 。对于homeroutes未处理的任何有效路由,它应该返回一个非空值。

  4. 最后,如果所有其他方法都失败,则调用onUnknownRoute

如果homeroutesonGenerateRouteonUnknownRoute都为 null,并且builder不为 null,则不会创建Navigator

源码分析
顶层的的Navigation 分析
MaterialApp 的 _MaterialAppState  源码
@override
Widget build(BuildContext context) {
  Widget result = _buildWidgetApp(context);
}
Widget _buildWidgetApp(BuildContext context) {
  final Color materialColor = widget.color ?? widget.theme?.primaryColor ?? Colors.blue;
//是否有使用路由
  if (_usesRouter) {
    return WidgetsApp.router(
...省略
    );
  }
//默认调用
//一个方便的小部件,它包装了应用程序通常需要的许多小部件。
//WidgetsApp提供的主要角色之一是绑定系统后退按钮以弹出导航器或退出应用程序。
  return WidgetsApp(
  ...省略
  );
}
_WidgetsAppState
@override
State<WidgetsApp> createState() => _WidgetsAppState();

bool get _usesRouter => widget.routerDelegate != null;
bool get _usesNavigator => widget.home != null
    || (widget.routes?.isNotEmpty ?? false)
    || widget.onGenerateRoute != null
    || widget.onUnknownRoute != null;

@override
Widget build(BuildContext context) {
  Widget? routing;
//判断使用路由
  if (_usesRouter) {
    routing = Router<Object>(
      restorationScopeId: 'router',
      routeInformationProvider: _effectiveRouteInformationProvider,
      routeInformationParser: widget.routeInformationParser,
      routerDelegate: widget.routerDelegate!,
      backButtonDispatcher: widget.backButtonDispatcher,
    );
//默认使用导航器
  } else if (_usesNavigator) {
    routing = Navigator(
//用于保存和恢复导航器状态(包括其历史记录)的恢复 ID。
//如果提供了恢复 ID,导航器将保留其内部状态(包括路线历史以及路线的可恢复状态)并在状态恢复期间恢复它。
//如果没有提供恢复 ID,则不会恢复路由历史堆栈,并且也会为各个路由禁用状态恢复。
      restorationScopeId: 'nav',
      key: _navigator,
//初始化默认路由  系统默认是/
      initialRoute: _initialRouteName,
//当应用程序导航到命名路由时使用的路由生成器回调。
      onGenerateRoute: _onGenerateRoute,
//默认onGenerateInitialRoutes=null。使用router方式可定义
//defaultGenerateInitialRoutes将路由名称转换为一组 [Route] 对象。
      onGenerateInitialRoutes: widget.onGenerateInitialRoutes == null
          ? Navigator.defaultGenerateInitialRoutes
          : (NavigatorState navigator, String initialRouteName) {
        return widget.onGenerateInitialRoutes!(initialRouteName);
      },
//当[onGenerateRoute] 生成路由失败时调用
      onUnknownRoute: _onUnknownRoute,
//此导航器的观察者列表。
      observers: widget.navigatorObservers!,
 此导航器是否应将路线更新消息报告回
      reportsRouteUpdateToEngine: true,
    );
  }
        ...省略其他代码
}
Navigator.push(context, route) 源码分析
static Future<T?> push<T extends Object?>(BuildContext context, Route<T> route) {
//实际 MaterialPageRoute
  return Navigator.of(context).push(route);
}
@optionalTypeArgs
Future<T?> push<T extends Object?>(Route<T> route) {
  //把数据包装_RouteEntry 推送
  _pushEntry(_RouteEntry(route, initialState: _RouteLifecycle.push));
//返回Future结果
  return route.popped;
}

List<_RouteEntry> _history = <_RouteEntry>[];
void _pushEntry(_RouteEntry entry) {
//添加历史记录
  _history.add(entry);
//刷新历史
  _flushHistoryUpdates();
//取消指针
  _afterNavigation(entry.route);
}

//有效的状态区间 

bool get isPresent {
  return currentState.index <= _RouteLifecycle.remove.index &&
         currentState.index >= _RouteLifecycle.add.index;
}
void _flushHistoryUpdates({bool rearrangeOverlay = true}) {
  //更改状态
  _flushingHistory = true;
  //获取最新的长度
  int index = _history.length - 1;
  //下一个对象
  _RouteEntry? next;
  //末尾对象-要推送的对象
  _RouteEntry? entry = _history[index];
  //上一个对象
  _RouteEntry? previous = index > 0 ? _history[index - 1] : null;
  //添加删除标记
  bool canRemoveOrAdd = false;
  //弹出的路由
  Route<dynamic>? poppedRoute;
  //顶部活动路由
  bool seenTopActiveRoute = false;
  //待处理的对象
  final List<_RouteEntry> toBeDisposed = <_RouteEntry>[];
  //循环
  while (index >= 0) {
    //当前是push状态
    switch (entry!.currentState) {
      case _RouteLifecycle.push:
      case _RouteLifecycle.pushReplace:
      case _RouteLifecycle.replace:
        entry.handlePush(
//绑定导航
          navigator: this,
//上一个路由
          previous: previous?.route,
//返回上一个有效的区间状态 在add 和remove 之间(状态说明看下面)
          previousPresent: _getRouteBefore(index - 1, _RouteEntry.isPresentPredicate)?.route,
//是不是第一个
          isNewFirst: next == null,
        );
        if (entry.currentState == _RouteLifecycle.idle) {
          continue;
        }
        break;
    ...省略其他状态代码
  }
    //通知导航观察员路线变化
   _flushObserverNotifications();
//列表已清除,请发送didChangeNext/didChangePrevious通知
   _flushRouteAnnouncement();
//宣布路线名称更改
  if (widget.reportsRouteUpdateToEngine) {
          final _RouteEntry? lastEntry = _history.cast<_RouteEntry?>().lastWhere(
    (_RouteEntry? e) => e != null && _RouteEntry.isPresentPredicate(e), orElse: () => null,
  );
  final String? routeName = lastEntry?.route.settings.name;
  if (routeName != null && routeName != _lastAnnouncedRouteName) {
    SystemNavigator.routeInformationUpdated(location: routeName);
    _lastAnnouncedRouteName = routeName;
  }
 }
//最后,删除所有标记条目的覆盖条目并进行处置他们
 for (final _RouteEntry entry in toBeDisposed) {
  for (final OverlayEntry overlayEntry in entry.route.overlayEntries)
    overlayEntry.remove();
  entry.dispose();
 }
//从新覆盖排列 更新Ui
 if (rearrangeOverlay) {
   overlay?.rearrange(_allRouteOverlayEntries);
 }
//恢复状态
 if (bucket != null) {
  _serializableHistory.update(_history);
 }
  _flushingHistory = false;
}

//路由周期
enum _RouteLifecycle {
  staging,
  add,
  adding,
  push, 
  pushReplace, 
  pushing, 
  replace, 
  idle, 
  pop,
  complete, 
  remove, 
  popping, 
  removing, 
  dispose, 
  disposed,
}
_RouteEntry
void handlePush({ required NavigatorState navigator, required bool isNewFirst, required Route<dynamic>? previous, required Route<dynamic>? previousPresent }) {
  //上一个状态
  final _RouteLifecycle previousState = currentState;
  //绑定navigator
  route._navigator = navigator;
  //开始动画
  route.install();
  if (currentState == _RouteLifecycle.push || currentState == _RouteLifecycle.pushReplace) {
    //开始推送调用动画
//实际是MaterialPageRoute.didPush
   final TickerFuture routeFuture = route.didPush();
    //更改状态在推送中
    currentState = _RouteLifecycle.pushing;
//推送结果回调
    routeFuture.whenCompleteOrCancel(() {
      if (currentState == _RouteLifecycle.pushing) {
        //完成更改状态
        currentState = _RouteLifecycle.idle;
        //再次刷新 这时候状态是idle
        navigator._flushHistoryUpdates();
      }
    });
  } else {
   ...省略
  }
  if (isNewFirst) {
    route.didChangeNext(null);
  }

  if (previousState == _RouteLifecycle.replace || previousState == _RouteLifecycle.pushReplace) {
    navigator._observedRouteAdditions.add(
      _NavigatorReplaceObservation(route, previousPresent),
    );
  } else {
//添加到观察者队列
    navigator._observedRouteAdditions.add(
      _NavigatorPushObservation(route, previousPresent),
    );
  }
}
ModalRoute
void install() {
  super.install();
//生成动画
  _animationProxy = ProxyAnimation(super.animation);
  _secondaryAnimationProxy = ProxyAnimation(super.secondaryAnimation);
}
//TransitionRoute
void install() {
  super.install();
  if (_animation!.isCompleted && overlayEntries.isNotEmpty) {
    overlayEntries.first.opaque = opaque;
  }
}
//OverlayRoute
@factory
Iterable<OverlayEntry> createOverlayEntries();

@override
List<OverlayEntry> get overlayEntries => _overlayEntries;
final List<OverlayEntry> _overlayEntries = <OverlayEntry>[];

@override
void install() {
//添加
  _overlayEntries.addAll(createOverlayEntries());
  super.install();
}
//ModalRoute
@override
Iterable<OverlayEntry> createOverlayEntries() {
//创建 ChangeNotifier
  return <OverlayEntry>[
    _modalBarrier = OverlayEntry(builder: _buildModalBarrier),
    _modalScope = OverlayEntry(builder: _buildModalScope, maintainState: maintainState),
  ];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值