关键词Navigator、Route、Overlay
默认情况下,一次路由,由Navigator(route管理类)发起,Overlay(Navigator的子节点,用来挂载route的界面)切换Route(别名、界面管理类)所携带的界面。
详情
Navigator一个StatefulWidget嵌套在MaterialApp内部,其状态类NavigatorState(class NavigatorState extends State with TickerProviderStateMixin)可以在路由界面内,通过Navigator.of(context)获取。
一个标准的路由实现Navigator.push(context, new MaterialPageRoute(builder: (_) { return MyHomePage(); })); 复制代码
push 内部
Futurepush (Route route) { route.install(_currentOverlayEntry); // 路由表 _history.add(route); // 路由动作开始,(设置焦点,开始动画) route.didPush(); return route.popped; }复制代码
route.install(_currentOverlayEntry)作用
1.先初始化动画相关
2. 会初始化两个界面,一个是 _modalBarrier黑色蒙层,和我们需要路由的界面 由 _buildModalScope方法返回IterablecreateOverlayEntries() sync* { yield _modalBarrier = OverlayEntry(builder: _buildModalBarrier); yield OverlayEntry(builder: _buildModalScope, maintainState: maintainState); }复制代码
_buildModalScope 返回的界面
_ModalScopeStatus( ... child: AnimatedBuilder( builder: (BuildContext context, Widget child) { // 界面切换动画 return widget.route.buildTransitions( context, widget.route.animation, widget.route.secondaryAnimation, ); }, child: _page ??= RepaintBoundary( child: Builder( builder: (BuildContext context) { // 我们需要路由的界面 return widget.route.buildPage( context, widget.route.animation, widget.route.secondaryAnimation, ); }, ), ), )复制代码
3.调用navigator.overlay.insertAll()插入第二部初始化的界面
void insertAll(Iterableentries, { OverlayEntry above }) { if (entries.isEmpty) return; for (OverlayEntry entry in entries) { assert(entry._overlay == null); entry._overlay = this; } // 更新界面 setState(() { final int index = above == null ? _entries.length : _entries.indexOf(above) + 1; _entries.insertAll(index, entries); }); }复制代码
Overlay 嵌套Stack,通过栈来管理界面
Widget build(BuildContext context) {... return _Theatre( onstage: Stack( fit: StackFit.expand, children: onstageChildren.reversed.toList(growable: false), ), offstage: offstageChildren, ); }复制代码