参看代码版别,1.18

整个 flutter 运用的工作都只是依据原生运用中的一个 view,比方 android 中的 FlutterView,flutter 中的页面切换依托于它的路由机制,也便是以 Naflutter结构优缺点vigator 为中心的一套路由功用,使得它能够完毕与原生类似且能够自界说的页面切换作用。

下面将介绍 flutter 中的路由完毕原理,fluttered包含初始android下载装置化时的页面加载、切换页面的底层机制等。

完毕基础

flutter 运用的工作需求依托 MaterialApp/CupertinoApp 这两个 Widget,他们分别对应着 android/ios 的规划风格,一起也为运用的工作供给了一些根柢的设备,比方与路由相关的主页面、路由表等,再比方跟整体页面展现相关的 theme、locale 等。

其间与路由相关的几项装备有 home、routes、initialRo复杂度调整因子ute、onGenerateRoute、onUnknownRoute,它们分别对应着主页面 widget、路由表(依据路由找到对应 widget)、初度加载时的路由、路由生成器、不知道路由署理(比方常见的 404 页面)。

MaterialApp/CupertinoApp 的子结flutter怎样读音发音点都是 WidgetsApp,只不过他们给 WidgetsAelementanimationpp 传复杂度剖析入了不同的参数,从而使得两种 Widget 的界面风格不一起。Navigator 便是在 WidgetsApp 中创立的,

Wid复杂度最优get build(BuildContext context) {
Widget nav复杂度英文igator;
if (_navigator != null) {
navigato复杂度调整因子r = Navigator(
key: _navigflutter值得学吗ator,
// If window.defaultRouteName isn't 'ios15beta2/', we should assume it was set
// intentionally via `setInitialRoute`, and should override whateverios15beta2
// is in [widget.initialRouteios15正式版别什么时候发布].
initialRoute: WidgetsBinding.instance.window.defaultRouteNameelement什么意思 != Navi复杂度剖析gator.defaultRouteName
? WidgetsBind复杂度oing.instance.window.defaultRouteName
: widget.复杂度排序initialRoute ??elementary school WidgetsBinding.instance.window.defaultRouteName,
onGenerateRoute: _onGenerateRoute,
onGenerateInitialRoutes: widget.onGenerateInitialRoutes == null
? Navigator.defaultGenerateInitialRoutes
: (NavigatorState navigator, String initialRouteName) {
retandroidstudio装置教程urn widget.onGenerateInitialRoute复杂度剖析s(initialRouios是什么意思teName);
},
onUnknownRoute: _onUnknownRo复杂度最高的是ute,
observers: widget.navig复杂度符号atorObservers,
)elements是什么牌子;
}
...
}

在 WidgetsApp 的 build 中复杂度排序第一个创立的便是 Navigator,首要看一下它的参数,首要,_navigator 是一个 GlobalKey,使得 WidgetsApp 能够经过 key 调用 Navigator 的函android什么意思数进行路由切换,也便是在 WidgetsBind复杂度ing 中处理 native 的路由切换信息的时ios模拟器分,毕竟是由 WidgetsApp 完毕的。其他这儿的 _navigator 应该只在 WidgetsApp 中有运用,其他地方需求运用一般是直接调用 Navigator.of 获取,这ios15beta2个函数会沿着 element 树向上查找到 NavigatorState,所以在运用中切换路由是需求被 Navigator 包裹的,不过由于 WidgetsApp 中都复杂度符号有生成 Navigator,开发中也不必考虑这些。

其他,便是关于底层获取上层 NavigatorElement 实例的方法,在 Elementelements翻译 树中有两种方法能够从底层获取到上层的实例,一种方法是运用 InheritedWidget,另一种便是直接沿着树向上查找(ancestorXXXOfExactType 系列),两种方法的原理根柢是一起的,只不过 InheritedWidgeios14.4.1更新了什么t 在树立树的进程中会一层ios体系层向下传递,而后者是运用的时分才向上查找,所以从这个视点来说运用 InheritedWidget 会高效些,可是 InheritedWidget 的优势不止如此,它是能够在数据发生改动的时分告知全部依托它的ios14.4.1更新了什么结点进行更新,这也是 ancestorXXXOfExactType 系列所没有的。

然后 iniandroid什么意思tialRios下载oute 规则了初始化时分的页面,由 WidgetsBiandroid下载nding.instanelementanimationce.window.defaultRouteName 和 widget.initialRoute 来决议android手机,不过前者优先级更高,由于这个是 native 中指定的,以 android 为例,在建议 FlutterActivflutter结构ity 的时分能够传入 route 字段指定初始化页面。

onGenerateRoute 和 onUnknownRoute 是获取 routeflutter中文官网 的战略,当 onGenerateRoute 没有射中时会调用 onUnelementsknownRoute 给定一个默许的页面,onGenerateInitiios15正式版别什么时候发布alRoutes 用于生产建议运用时的路elementaryFlutter列表,它有一个默许完毕 defaultGenerateInitialRoutes,会依据传递的 initialRouteName 选择不同的 Route,假定传入的 initialRouteName 并不是默许的主页面路由 Navigator.defaultRouteName,flutter 并不会将 initRoute 作为主页面,而是将默许路由入栈了之后再入栈android是什么手机牌子 initRoute 对应的页面,所以假定在这之后再调用 pflutter是什么意思opRoute,是会回来到主页面的

observers 是路由切换的监听列表,能够由外部传入,在路由切换的时分做些操作ios8备忘录,比方 HeroController 便是一个监听者。

Navigator 是一个 StatefulWidget,在 NavigatorState 的 initState 中完毕android手机了将 initRoute 转化成 Route 的flutter值得学吗进程,并调用 push 将其入栈,生成 OverlayEnflutter是什么意思try,这个会持续传递给下层担任闪现页面的 Overlay 担任展现。

在 push 的进程中,route 会被转化成 OverlayEntry 列表存放,每一个 OverlayEntry 中存储一个 WidgetBuilder,从某种视点来说,Overla复杂度最高的是yEntry 能够被认为是一个页面。全部的页面的和谐、展现是经过 Overlay 完毕的,Overlay 是一个类似于 Stack 的结构,它能够展现多个子结点。在它的 initState 中,

void initState() {
super.initState();
insertAll(widget.initialEntries);
}

会将 initialEntries 都存到 _entries 中。

Overla复杂度最高的是y 作为一个能够依据路由承认展现页面的控件,它的完毕其实比较简略:

Widget build(Buflutter开发的app有哪些ildContext context) {
// These lists are filled backwards. Forelements the offstage children thelementsat
// doelementses not matter since they aren't rendered, but for the onstage
// children we reverse the list be复杂度调整因子low before adding it to the tree.
final List<Widget> onstageChildren = <Widget>[];
final List<flutter值得学吗Widget> offstageChi复杂度英文ldren = &androidstudio装置教程lt;Widget>[];
bool onstage = true;
for (int i = _entries.length - 1; i >=复杂度o 0; i -= 1)复杂度英文 {android是什么手机牌子
final OverlayEntry entry = _entries[i];复杂度排序
if (onstage) {
onstageChildren.add(_OverlayEntry(entry));
if (entry.opaque)
onstage = false;
} else if (entry.iOSmaintainState) {
offstageChios15ildren.add(TickerMode(enabled:复杂度排序 false, child: _OverlayEntryelements是什么牌子(entry)));
}
}
return _Theaandroid体系tre(
onstage: Stack(
fit: StackFiios14.4.1更新了什么t.expand,
children: onstageChild复杂度怎样核算的ren.reversed.toL复杂度o(1)什么意思ist(growable: false),
),
offstage: offstageCflutteredhildreAndroidn,
);
}

buiflutter值得学吗ld 函数中,将全部的 OverlayEntry 分成了可见与不复杂度o行见两部分,每一个 OverlayEntry 生成一个 _Oveandroid的drawable类rlayEntry,这是一个 StatefulWidgeflutter中文官网t,它的作用首要是担任操控当时页重绘,都被封装成 然后再用 _Thea复杂度怎样核算的tre 展现就完了,在 _Theatre 中,可见/不可见的子结点都会转成 Element,可是在制作的时分,_Theatre 对应的 _RenderTheElementatios15beta2re 只会把可见的elements子结点制作出来。

判别某一个 Overlayflutter结构优缺点Entry 是否能够彻底flutter是什么意思遮挡上一个 OverlayEntrios8备忘录y 是经过它的 opaque 变量判其他,而 opaque 又是由 Ro复杂度英文ute 给出的,在ios最好玩的手游页面动画ios8备忘录实施时,这个值会被设置成 false,然后在页面切换动画实施完了之后就会把 Route 的 opaque 参数赋值给它的 OverlayEntry,一般状况下,窗口对应的 Rouelementary是什么意思te 为 false,页面对应的 Route 为 true。

所以说在页面切换之flutter开发的app有哪些后,上一个页面一向都是存在于 element 树中的,只不过在 RenderObject 中没有将其制作出来,这一点在 Flutter Outline 东西里面也能够体现elementary school。从这个视点也能够了解为,在 flutter 中页面越elements是什么牌子多,需求处理的进程就越多,虽然不需求制作底部的页面,可是整个树的根柢遍历仍是会有的,android平板电脑价格这部分也算是开支。

_routeiOSNamed

flutter 中进行页面处理首要的依托路由处理体系,它的进口便是 Navigator,它所处理的东西,本质上便是承载着用户页面的 Route,可是在 Navigator 中有很多函数是 XXXName 系列的,它们传的ios体系不是 Route,elements是什么牌子而是 RouteName,据个人了解,这个首要是便当开发引进的,我们能够在 MaterialApp/CupertinoAp复杂度调整因子p 中直接传入路由表,每一个名字对应一个 WidgetBuilder,然后结合 pageflutter值得学吗RouteBuilder(这个能够自界说,不过 MaterialApp/CupertinoAelements翻译pp 都有默许完毕,能够将 WidgetBuilder 转成 Route),便能够完毕从 Routeelements是什么牌子Name 到 Route 的转化。

Route<T> _routeNamed<T>(String name, { @required Object arguments, bool allowNull = false }) {
if (allowNull && widge复杂度最高的是t.onGenerateRoute == null)
return null;
final Roios模拟器uteSettings settings = RouteSettingsAndroid(
name: name,
arguments: arguments,
);
Route<T> route = widget.onGenerateRouteflutter中文官网(settings) as Route<T>;
if (route == null && !alelementary schoollowNull) {
route = widgetFlutter.onUnknownRoute(settings) as Route<Tfluttering>;
}
return route;
}

这个进程分三步,生成 RouteSettings,调用 onios最好玩的手游GenerateRoute 从路由表中拿到对应的路由,假定android下载无射中,就调用 onUnkn复杂度排序ownRouelement什么意思te 给一个类似于复杂度最优 404 页面的东西。

onGenerateRoute 和 onUnknownRoute 在构建 Navigator 时传入,在 WidgetsApp 中完毕,

Roelementary是什么意思ute<dynamic> _onGenerateRoute(RouteSettings settings) {
final String name = settings.name;
final WidgetBuilder pflutter结构优缺点ageContentBuilder = nameandroid什么意思 == Navigator.defaultRouteName &&ios15 widgios体系et.home != null
? (BuildContext context) => widget.home
: widgetios14.4.1更新了什么.flutteredroutes[name];
if (pageContentBuilder != null) {
finaandroid是什么手机牌子l Route<dynamic> route = widget.pageRouteBuilder<dynamicfluttered>(
settings,
pag复杂度符号eContentBuilder,
);
return route;
}
if (widget.onGenerateRoute != null)
return widandroid手机get.onGenerateRoute(settings);
return null;
}

假定是默许的路由会直接运用给定android体系的 home 页面(假定有),不然就直接到路由表查,所以本质上这儿的 home 页面更多的是一种标志,身份的标志,没有ios体系也无所谓。其他路由表首要的产出是 WidgetBuilder,它需求复杂度最高的是经过一次包装,成为 Rflutteringoflutter中文官网ute 才是制品,或者假定不想运用路由表这种,也能够直接完毕 onGenerateRout复杂度o(1)什么意思e 函数,依据 RouteSetting复杂度调整因子 直接生成 Routflutter开发的app有哪些e,这个就不仅仅是回来 WidgetBuandroid体系ilder 这么简略了,需求自己包装。

onUnknownRoute 首要用于兜底,供给一个类似于 404 的页面,它也是需求直接回来 Route。

_flushHistoryUpdateselementui

不知道从哪一个版别初步,flutter 的路由处理引进了状况,与之前每一个 push、pop 都单独完毕不elements是什么牌子同,全部的路由切换操作都是用状况标明,一起全部的 routeAndroid 都被封装成 _RouteEntry,它内部有着关于 Route 操作的完毕,但都被区分为比较小的单元,且都依托状况来实施。

状况是一个具有递进联络的枚举,每一个 _RouteEntry 都有一个变复杂度怎样核算的量存放当时elementary的状况,在 _flushHistoryUpdates 中会遍历全部的 _RouteEntry 然后依据它们当时的状况进行处理,一起处理完毕之后会切换它们的状况,再进行其他处理,这样的优点很明显复杂度怎样核算的,全部的路由都放在一起处理之后,整个流程会变得更加清楚,且能够很大程度上进行代码复用,比方 push 和 pushReplacement 两种操作,这在之前是需求在两个方法中单独完毕的,而现在他们则能够放在一起单独处理,不ios15正式版别什么时候发布同的只需后者比前者会多一个 reflutter怎样读音发音move 的操作。

关于 _flushHiflutteringstoryUpdates 的处理进程:

void _flushHistoryUpdates({bool rearrangeOverl复杂度最优ay = true}) {
assert(_debugLocked && !_debugUpdatingPage);
// Clean up the list, sending updates to the rouandroid下载tes that changed. Notably,
// we don't send the didChangePrevious/didChangeNext updates to those that
// did not change at this point, because wflutter中文官网e're not yet sure exactly what the
// routes will be at the end of the day (some might get disposed).
iflutter结构优缺点nt index = _history.length - 1;
_RouteEntry next;
_RouteEntry entry = _history[indexios是什么意思];
_RouteEntelements翻译ry previous = index > 0 ? _history[index - 1] : null;
bool canRemoveOrAdd = false; // Whether there is a fully opaque route on top to silently remove orflutter中文官网 add route underneath.
Route复杂度排序<dynam复杂度符号ic> poppedRoute; // Tflutter中文官网he route that should trigger didPopNext on the top active route.
bool seenTopActelements是什么牌子iveRoute = false; // Whether we've seen the route that would get didPopNext.
final List<_RouteEelementuintry> toBeflutteringDisposed = <_RouteEntry>[];
whiios下载le (inde复杂度x >= 0) {
switch (entry.currentState) {
// ...
}
index -= 1;
next =flutter值得学吗 entry;
entry = previous;
previous = index > 0 ? _hist复杂度剖析ory[indeelementary schoolx - 1] : null;
}
// Now that the list is clean, send the didChangeNext/didChangePrevious
// notific复杂度符号atflutteredions.
_fios8备忘录lushRouteAnnouncement();
// Announces route name changes.
final _RouteEntry lastEntry = _history.las复杂度怎样核算的tWhere(_RouteEntry.isPresentPredicate, orElse: () => null);
final String routeName = lastEntry?.route?.settings?.name;
if (routeName != _lastAnnouncedRouteNaelementary是什么意思me) {
RouteNotificationMessios是什么意思ages.maybeNotifyRouteChange(routeName, _lastAnnouncedRouteName);
_lastAnnouncedRouteName = routeNios模拟器ame;
}
/flutter值得学吗/ Lastly, removes the overlay entries of all marked enandroidstudio装置教程tries and disposes
// them.
for (final _Rios15beta2outeEntry entry in toBeDispoandroid手机sed) {
for (final OverlayEntry overlayEntry in entryiOS.route.ofluttershyverlayEntries)
overlayEntry.remove();
entry.dispose();
}
if (rearrangeOverlay)elements是什么牌子
overlay?.reelementary是什么意思arrange(_allRouteOverlayEntries);
}

以上是除了状况处理之外,一次 _flushHistoryUpdflutteredates 的全进程,首要它会遍历整个路由列表,依据状况做不同的处elementanimation理,不过一般能够处理到的也不过最上层一两个,其他的多半是直接跳过的。处理完了之后,调用 _flushRouteAnnouncement 进行路由之间的前后链接,比方进行动画的联动等,

void _fluselementaryhRouteAnnouncemflutter开发的app有哪些ent() {
int index = _history.length - 1;
while (index >= 0) {
finflutteringal _RouteEntry entry = _history[ind复杂度最高的是ex];
if (!entry.suitableForAnnouncemelementary是什么意思ent) {
index -= 1;
continuAndroide;
}
final _RouteEntry next = _getRouteAfter(indexelements翻译 + 1, _Roflutter是什么意思uteEntry.suitableForTr复杂度最高的是ansitionAnimationPredicate);
if (next?.route != entry.lastAnnouncedNextRoute) {
if (entry.shouldAnnounceChangeToNext(next?.route)) {
entry.route.didChangeNext(next?.route);
}
entry.lastAnnouncedNextRoute = next?复杂度调整因子.route;
}
final _RouteEntry previous = _getRouteBefore(index - 1, _RouteEntry.suitableForTransitionAnimationPredicate);
if (previous?.route != entry.lastAnnouncedPreviousRoute) {
entry.route.didChangePrevious(previous?.route)elementui;
entry.lastAnnouncedPreviousRoute = previous?.route;
}
index -= 1;
}
}

其完毕也比较清楚,对每一个 _RouteEntry,经过调用 didChangeNext 和 didChanflutter中文官网gePrevious 来树立联络,比方在 didChangeNext 中ios体系绑定当时 Route 的 secondaryAnimation 和下一个路由的android下载 animation 进行动画联动android是什么手机牌子,再比方在 didChangePrevious 中获取上一个路由的 titl复杂度最优e,这个能够用于 CupertinoNavigationBar 中 baandroid软件开发ck 按钮展现上一页面的 title。

然后调用 maybeNotifyRouteChange 宣布告知,指定当时正在处于展现状况的 Route。

毕竟,遍历 toBeDisposed 实施 _RouteEntry 的毁掉,这个列表会保存上面循flutter中文官网环处理进程中,承认需求移出的fluttered _RouteEntry,经过调用 OverlayEntry remove 函数(它会将自己从 Overlay 中移除)和 OverlayEntry dispose 函数(它会调用 Route 的 dispose,进行资源开释,比方 TransitionRoute 中 AnimationControelementuiller 毁掉)。

毕竟再看关于状况的处理,以下是全部的状况:

enum _RouteLifecycle {
staging, // we wilflutteredl wait for transition delegate to decide what to do with this route.
//
// routes that are present:
//
add, // we'llfluttering want to run install, didAdd, etc; a rflutter结构优缺点oute createlementary schooled by onGenerateInitialRoutes or by the initial widget.复杂度最优pages
adding, // we'll want to run influtter是什么意思stall, didAdd, etc; a route created by onGenerateInitialRoutes or by the initial widget.pages
//elementui routes that are reaios15beta2dy for transflutteringition.
push, // we'll want to run install, didPush, etc;elements是什么牌子 a route added via push() and friends
pushReplace, // we'll want to run install, didelements翻译Push, etc; a route added via pushReplace() aflutterednd friends
pushing, // we're waiting for the future from didPush to complete
replace, // we'll want to run install, didReplace, etandroid的drawable类c; a route added via replace() and friends
idle, // route is being harmless
//
// routes thaios8备忘录t are not present:
//
// routes that should be included in route ann复杂度英文ouncelements是什么牌子ement and should still listen to transition changes.
pop,elements是什么牌子 // we'll want to call diFlutterdPop
remove, // we'll want toflutter值得学吗 run didReplace/didRemove etc
// routes should not be included in route announcement but shoflutter值得学吗uld still listen to transition changes.
popping, // we're waiting for the route to call finalizeRoutefluttershy to switch to dispose
removinios体系g, // we are waiting for subsequent routes to be done animating, then will switchandroid平板电脑价格 to dispose
// routes that are completely removed from the navigator and overlay.
dispose, // we will dispose the route momentarily
disposed, // we haflutter是什么意思ve disposed the route
}

本质上这些状况分为三类,add(处理初始化的时分直接增加),puandroid下载sh(与 add 类似,可是增加了动画的处理),pop(处理页面移出),remove(移出某个页面,相对 pop 没有动画,也没有方位约束)。

add

add 方法增加路由现在还只用于在运用初始化是增加初始化页面运用flutter是什么意思,对应的是在 NavigatorState 的 initState 中,

void initState() {
super.initStateFlutter();
for (final NavigatorObserveandroid下载装置r observer in widflutter中文官网get.observers) {
assert(observer.navigator == null);
observer._navigator = this;
}
String initialRoute = widget.initia复杂度最优lRoute;
if (wid复杂度geios模拟器t.pages.isNotEmpty) {
_history.addAll(
widget.pages.map((Page<dynamic> page) => _RouteEntry(
page.createRoute(context),
initiaios是什么意思lState: _RouteLifecycle.add,
))
);
} else {
// If there is no page provided, we will need to prov复杂度剖析ide default route
// to initialize the navigator.
initialRoute = initialRouelementary schoolte ?? Navigator.deflutteredfaultRouteName;
}
if (initialRoute != null) {
_history.addAll复杂度排序(
widget.onGenerateInitiios最好玩的手游alRoutes(
this,
widget.initios15beta2ialRoute ?? Navigator.defaultRouteName
).map((Route<dynamic> route) =>
_Rouios最好玩的手游teEntry(
route,
initialState: _RouteLifecycle.add,
),
),
);
}
_flushHistelements是什么牌子oryUpdates();
}

它会将从 onGenerateInitialRoutes 得来的全部初始路由转成 _RouteEntry 参与到 _history,此刻它iOS们的状况是 _Rout复杂度eLifecycle.add,然后便是调用 _flushHistoryUpdates 进行处理。

void _flushHisandroid的drawable类toryUpdates({bool rearrangeOverlay = true}) {
// ..android什么意思.
while (index >= 0) {
switch (entry.currentState) {
case _RouteLifecycle.add:
assert(rearrangeOverlay);
entry.handl复杂度oeAdd(
navigator: this,
);
assert(entry.curios下载rentState ==elements是什么牌子 _RouteLifecycle.adding);
continue;
case _elementanimationRouteLifecycle.adding:
if (caios14.4.1更新了什么nRemoveOrAdd || next =Android= null) {
entry.didAdd(
navigator: this,
previous: previous?.route,
pelementaryreviousPresent: _getRouteBefore(index - 1, _RouteEntry.isPresentPiOSredicateandroid平板电脑价格)?.route,
isNewFirst: next == nulios下载l
);
assert(eandroid体系ntry.cios15正式版别什么时候发布urrentState == _RouteLifecycle.idle);
continue;
}
break;
case _RouteLifecycle.idle:
if (element滑板!seenTandroid下载装置opActiveR复杂度剖析oute && poppedRoute != null)
entry.handleDidPopNextAndroid(poppedRoute);
seenTopActiveRoute = true;
// This route is idle, so we are allowed to riOSemove subsequent (earlier)
// routes that are waiting to be removed silently:
canRemoveOrAdd = true;
break;
// ...
}
index -= 1;
next = entry;
entry = previous;
previous = index > 0 ? _history[index - 1] : null;
}
// ...
}

addelement滑板 路途首要会调用两个函数,handleAflutter值得学吗dd 和 didAdd,

void handleAdd({ @required NavigatorState navigator}) {
assert(currentState == _RouteLifecycle.add);
assert(navigator != null);
assert(navigator._debugLocked);
assert(roios体系ute._navigator == null);
route._navigator = nandroid软件开发avigator;
route.install();
ass复杂度英文ert(route.复杂度o(1)什么意思overlayEntries.isN复杂度otEmpty);
currentState = _Roflutter值得学吗uteLifecycle.adding;
}

install 函数能够看作是 Route 的初始化函数,比方在 Modaios体系lRoute 中创立 ProxyAnimation 来处理一些动画的实施,在 Transitio复杂度onRoute 中创立了用于实施切换动画的 AnimationController,在 OverlayRoute 中完毕了当时 Route 的 O复杂度英文verlayEntry 的创立及刺进。createOverlayEnt复杂度ries 用于创立 OverlayEntry,其完毕在 ModalRoute,

Iterable<OverlayEntry> cr复杂度怎样核算的eateOverlios是什么意思ayEntries() sync* {
yield _modalBaflutter值得学吗rrier = OverlayEntry(android是什么手机牌子builder: _buildModalBarrier);
yieios是什么意思ld Ov复杂度怎样核算的erlayEntry(builder: _buildModalScope, maintainState: mandroid的drawable类aintainState);
}

每一个 Route 都能生成两个 OverlayEntry,一个elementanimation是 _buildModalBarrier,它能够生成两个页面之间的屏障,我们能够利用它给新页面设置一个背景色,一起还支撑动画过渡,另一个是 _buildModalSelementary是什么意思cope,它生成的便是这个页面实在的内容,外部会有多层包装,最底层便是 WidgetBuilder 创立的 widget。

大致看下两个函数的完毕,

Widget _buildModalBarrier(BuildContext context) {
Widget bandroid软件开发arrier;
if (baandroid什么意思rrierC复杂度剖析olor != null && !offstage) { // changedInternalState is called if these update
assert(barrierColor != _kTransparentfluttered);
final Animation<Color> color = animation.drive(
ColorTween(
begin: _kTransparent,
end: barrierColor, // changedInternalState is called if this updates
).chain(_easeCurveTween),
);
barrier = AnimatedModalBarrier(
color: color,
dismissib复杂度英文le: barrierDismissib复杂度怎样核算的le, // changedInternalState is called if this updates
semanticsLabel: barrierLaelements翻译bel, // changedInternalState is called if this updates
barriflutterederSemanticsDismissible: semanticsDismissible,
);
} else {
barrier = ModalBarri复杂度调整因子er(
dismis复杂度osible: barrierDismissible, // changedInternalState is call复杂度o(1)什么意思ed if this updates
semanticsLabel:复杂度英文 barrierLabel, // changedIelement什么意思nternalState is called if this updates
barrierSemanticsDismissible: semanticsDismissible,
);
}
return IgnorePointer(
ignoring: animation.status == AnimationStatus.reverse || // celements翻译hangedInternalState is called when this updates
animation.status == Aandroid什么意思nimationStaelement什么意思tus.dismissed, // dismissed is possiios是什么意思ble when do复杂度剖析ing a manual pop gesture
child: barrie复杂度最优r,
);
}

ModalBaelementaryrrier 是两个 Route 之间的屏障,它能够经过颜色、拦截事件来标明两个 Route 的隔绝,复杂度调整因子这些都是能够装备的,这儿 IgnorePflutteredointer 的作用是为了在实施切换动画的时分无法照应时间。

Widget _buildModflutteredalios14.4.1更新了什么Scope(BuildContext context) {
returnflutter结构优缺点 _modalScopeCache ??= _ModalScope<T>(
key:iOS _scopeKey,
route: this,
// _ModalScope calls buildTransitions() and buildChild(), defined above
);
}
Widget build(BuildContext context) {
return _ModalScopeStatus(
route: widget.route,
isCurreflutter结构优缺点nt: widget.route.isCurrent, // _routandroid下载装置eSetState is called if this updates
canPop: widget.route.caelementarynPop, // _routeS复杂度oetState is called if this updates
child: Offstage(
offstage: widget.route.offstage, // _routeSetState is called if this updaandroid什么意思tes
child: PageStorage(
bucket: widget.route._stflutter结构优缺点oraFluttergeBucket, // immutable
child: FocusScflutter结构ope(
node: focusScopeNode, // immu复杂度otable
child: RepaintBoundary(
child: AnimatedBuilder(
animation: _listenable, // immutaelementsble
builder: (BuildContex复杂度t context, Widget child) {
return widget.route.buildTransitionflutter开发的app有哪些s(
context,
widget.route.animation,
widget.roios体系ute.secondar复杂度剖析yAnimation,
IgnorePointer(
ignoring: widget.route.animation?.status == AnimationStatus.elementaryreverse,
child: child,android下载
),
);
},
child: _page ??= RepaintBoundary(
key: w复杂度idget.route._subtreeKey, // immutandroid软件开发able
child: Builder(
builder: (BuildContext context) {
return widget.route.buildPage(
coios模拟器ntext,
widget.route.animation,
widget.rouflutter结构优缺点te.secondaryAnimation,
);
},
),flutter怎样读音发音
),
),
),
),
),
),
);
}

_ModalScope 需求承载复杂度剖析用户界面的展现,它的 build 函数能够看到在 widget.route.buildPage 出用户界说的页面之上有很多层,能够一层一层看android软件开发下大致作用:

  1. _ModalScopeStatus,承继自 InheritedWidget,用于给底层结点供给数据
  2. Offstage,能够经过 offstage 变量操控是否制作
  3. PageStorage,它供给了一种存储战略,也便是 PageStorageBuckfluttershyet,这个类能够给某一个 BuildContext 绑定特定的数据,支撑写入和读取,可用flutter中文官网于某一个 widget 的状况存储等
  4. FocusScope,用于焦点处理用,一般只需获取焦点的复杂度控件elementary才干接收到按键信息等
  5. RepaintBoundary,操控重绘规模,意在减少不必要的重绘
  6. AnimatedBuilder,动画操控 Widget,会依据 animatioios下载n 进行 rebuild
  7. widget复杂度剖析.route.buildTransitions,它在不flutter开发的app有哪些同的 Route 中android软件开发能够有不同的完毕,比android是什么手机牌子如 Android 的默许完毕是自下向上渐入,ios 的默许flutter结构完毕是自右向左滑动,其他fluttershy也能够经过自界说复杂度英文 Routios最好玩的手游e 或自界说 ThemeData 完毕自界说ios8备忘录的切换动画,还有一点需求阐明,Route 中的动画分为 animation 和 secoandroid下载装置ndaryAnimation,其间 animation 界说了自己复杂度符号 push 时的动画,secondaryAnimation 界说的是新页面 push 时自己的动画,举个比方,在 ios 风格中,新页面自右向左滑动,上element什么意思一个页面也会滑动,此刻操控android软件开发上一个页面滑动fluttered的动画便是 secondaryAnimation
  8. IgnoreelementanimationPointer,相同是用于页面切换动画实施中,制止用户操ios15beta2
  9. RepaintBoundary,这儿的考量应该是考虑到上android下载层有一个动画实施,所以这儿包一下避免固定内容重绘
  10. Buiios15beta2lder,Builder 的仅有作用应该是供给 Buios15正式版别什么时候发布ildC复杂度排序ontext,虽然说每一个 builandroid下载装置d 函数都有 BuildContext 参数,但这个是当时 Widget 的,而不是直属上级的,elements这或许有点笼统,比方说下面的 buildPage 需求运用 BuildContext 作为参数,那么假定它需求运用 context 的 ancestorStateOfType 的话,实践上便是从 _ModalScopeState 初步向上查找,而不是从 Builder 初步向上查找
  11. widget.flutteredroute.buildPage,这个函数内部elementui便是运用 Route 的 WidgetBuilder 创立用户界面,当然不同的 Route 或许还会在这儿再次进行包装

以上便是一个页面中,从 Overlay(说是 Overlay 不是那么合理,可是在此先省掉中心的 _Theatre 等) 往下的布局嵌套。新的 OverlayEntry 创立完毕之后,会把它们android软件开发都传iOS递到 Overlay 中,且在这个进程中会调用 Overlay 的 setState 函数,央求从头制作,在 Overlay 中完毕新旧页面的ios模拟器切换。

以上是 install 的整flutter中文官网个进程,实施完了之后把 currentStateios14.4.1更新了什么 置为 addiandroid下载装置ng 回来。

此处有一点需求留意,while 循环会自上往下遍历全部的iOS _RouteEntry,可是当一个接连操作尚未完毕时,它是不会去实施下一个flutter开发的app有哪些 _RouteEntry 的,其完毕就在于代码中的 continue 关键字,这个关键字会直接回来实施下一次循环,可是并没有更新当时 _RouteEntry,所以实践处理的仍是同一个路由,这种一般用于elements翻译 _RouteEntry 状况发生改变,且需求接连处理复杂度最优的时分,所以关于 add 来说,实施完了之后会马上实施 adding 代码块,也便是 didAdd,

void didAdd({ @re复杂度怎样核算的quired NavigatorState navigator, @required bool isNewFirst, @reios14.4.1更新了什么quired Route<dynamelementary是什么意思ic> previous, @required Route<dynamic>复杂度剖析 pflutter结构优缺点reviousPresent }) {
route.didAdd();
currentState = _RouteLelement什么意思ifecycle.idle;
if (isNewFirst) {
route.didChangeNext(null);
}
for (final NavigatorObserver observer in navigator.widget.observers)
oelement什么意思bserver.didPush(ios模拟器route,Flutter previousPresent);
}

Route 的 diflutter值得学吗dAandroid什么意思dd 函数标element什么意思明这个路由现已增加完毕,它会做一些收尾处理,比方在 TransitionRoute 中更新 AnimationController 的值到最大,并设置通明等。然后 didAdd 将状况置为 idle,并调用全部监听者的 didPush。idle 标明一个 _RouteEntry 现已处理完毕,后续只需 pop、replace 等操作才会需求从头处理,add 进程到这儿也能够完毕了。

push

Future<T> push复杂度最优<T extends Object>(Route&ltandroid平板电脑价格;T> route) {
assert(!_debugLocked);android的drawable类
assert(() {
_debugLocked = true;
return true;
}());
assert(route != null);
assert(route._navigator == null);
_history.add(_RouteEntry(route, initialState: _RouteLifecycle.push));
_flushHistoryUpdates();
assert(() {
_debugLocked = false;
return true;
}());
_afterNavigation(route);
ret复杂度urn route.popped;
}

pushElement 进程便是将 Routeandroid下载装置 封装成 _RouteEntry 参与到 _history 中并调用 _flushHistoryUpdates,它的初始状况时 push,并在复杂度毕竟回来 route.popped,这是一个 Future 目标,能够用于Element前一个页面接收新的页面的回来作用,这个值是在当时路由 pop 的时分传递的。

void _flushHistoryUpdates({bool randroid软件开发earrangeOverlay = true}) {
//Element ...
while (index >= 0) {
switch (entry.currentState) {
// ...
case _RouteLifecycle.push:
caseflutter结构优缺点 _Routandroid软件开发eLifecycle.pushRandroid软件开发eplace:
case _Rios下载outeLifecycle.replacandroid什么意思e:
assert(rearrangeOverlay);
entry.handlePush(
navigator: this,
previous: previous?.route,
previousPresent: _gios8备忘录etRouteBefore(index - 1, _RouteEntry.android的drawable类isPresentPredicate)?.route,
isNewFirst: next =复杂度最高的是= null,
);
assert(entry.currentState != _RouteLifecycle.push);
assert(entry.currentState != _RouteLifecycle.pushios14.4.1更新了什么Replace);
asserandroid平板电脑价格t(entry.currentState !=复杂度排序 _RouteLifecycle.replace);
if (entry.currentState == _RouteLifecycle.idle)fluttershy {
continue;
}
breaelement滑板k;
case _RouteLifecycle.pushing: // Will exit thiselements是什么牌子 state whenandroidstudio装置教程 animation completes.
if (!seenTopActiveRoute && poppedRoute != null)
entry.handleDidPopNextelementui(poppedRoute);
seenTopActiveRoute = true;android手机
break;
case _RouteLifecycle.idle:
if (!seenTopActiveRoute && poppedelementanimationRoute != null)
entry.handleDidPopNext(poppedRoute);
seenTopActiveRoute = true;
// This route is idle, so we are allowed to remove subsequent (earlier)
// routes that are waiting to be removed silently:
canelementanimationRemoveOrAdd = true;
break;
// ...
}
index -= 1;
next = entry;
entry = previous;复杂度最高的是
previous = index > 0 ? _history[index - 1] : null;
}
// ...
}

这儿将 push、pushReplace、replaceelements是什么牌子 都归为了一类,它会先调用 handlePush,这个函数中其实包含了 add 进程中的 handleAdd、didAdd 两个函数的功用,比方调用 install、调用 didPush,不同的是,push/pandroid手机ushReplace 会有一个过渡的进程,即先实施切换动画,此刻它的状况会变为 pushing,并在动画实施完时切到 idle 状况并调用 _flushHistoryUpdates复杂度o 更新,而 replace 则直接调用 didR复杂度调整因子eplace 完毕页面替换,从这儿看,这个应该是没有动画过渡的。后边仍是相同,调用告知函数。

pop

pelements翻译op 的进程与上面两个不太相同,它在 Nflutter结构优缺点avigatorState.pop 中也有一些操作:

void pop<T extends Object>([ T result ]) {
assert(!_debugLocked);
assert(() {
_debugLocked = true;
returnflutter怎样读音发音 true;
}());
final _RouteEntry eandroid平板电脑价格ntry = _history.lastWhere(_RouteEntry.isPresentPredicatefluttered);
if (entry.hasPage) {
if (widget.onPopP复杂度o(1)什么意思age(entry.route, result))
entry.currentState = _RouteLiios15beta2fecycle.pop;
} else {
entryflutter是什么意思.pop<T>(result);
}
if (entry.currentState == _RouteLifecycle.pop) {
// Flush the history if the route actually wants to be popped (the pop
// wasn't handled internally).
_flushHistoryUpdates(rearrangeOverlay: false);
assert(entry.route.iOS_popCompleter.isCompleted);
}
assert(() {
_debugLocked = false;
return true;
}());
_afterNaviga复杂度符号tion<dynamic>(entry.route);
}

便是调用 _RouteEntry 的 pop,在这个函数中它会调用 Route 的 didPop,完毕回来值的传递、移出动画建议等。可是在 Oios下载verlayRo复杂度ute 中:

bool didPop(T result) {
final bool returnValue = super.didPop(result);
assert(returnValue);
if (finishedWhenPopped)
navigator.finalizeflutter怎样读音发音Route(this);android是什么手机牌子
return returnValue;
}

finalizeRoute 的调用需求依托 finishedWhenPopped 的值,这个值在子类中能够被修正,比方 TransitionRoute 中它便是 false,了解也很简略,在 TransitionRoute 中实施 didPop 之后也不能直接就毁掉 Route,而是先要实施ios15beta2移出动画,而假定不需求实施动画,则能够直接调用,不然就在动画实施完再实施,这一点是经过监听动画状况完毕的,在 TransitionRoute 中。

void finalizeRoute(Route&element什么意思lt;dynamic> route) {
// FinalizeRoute may have been called while we were already locked as a
// responds to route.didPoios最好玩的手游p(). Make sure to leave in thflutter怎样读音发音eios8备忘录 state we were in
// before the call.
bool wasDebugLocked;
assert(() { wasDebugLocked = _debugLocked; _debugLocked = true; return true; }());
assert(_history.where(_RouteEntry.isRoutePredicate(route)).length == 1);
final _RouteEntry entry =  _history.firstWheandroid平板电脑价格re(_RouteEntryandroid下载.isRouelementuitePredicate(route));
if (entry.doingPop) {
// We were called synchronously from Route.didPop(), but didn't process
// the pop yet. Let's do that now beforeflutter中文官网 finalizing.
entry.currentState = _flutteredRouteLifecycle.pop;
_flushHistoryUpdates(rearrangeOverlay: false);
}
assert(entry.currentState != _RouflutteredteLifecycle.pop);
entry.finaliziOSe();
_flushHistoryUpdates(rearrangeOverlay: false);
aandroid什么意思sandroid软件开发sert(() { _debugLocked = wasDebugLocked; return true; }());
}

在 finalizeRoute 中,它会判别是否正在 pop 进程中,假定是,就说复杂度o明此刻是直接调用的 finalizeRoute,复杂度o那就需求先实施 pop 状况的操作,再实施 dispose 操作,将状况切换到 dispose 进行处理,复杂度最优假定不是,就阐明调用这个函数的时分,是动画实施fluttershy完的时分,flutter中文官网那么此刻 pop 状况处理现已完毕,所以跳过了 pop 处理的进elements是什么牌子程,如上。下面就看一下 pop 进程做的处理。

void _flushHistoryUpdates({bool rearrangeOverlay = true}) {
// ...
whilelementse (index >= 0) {ios8备忘录
switch (entry.cu复杂度最高的是rrentState) {
// ...
case _RouteLifecycle.pop:
if (!seenTopActiveRoute) {
if (poppedRoute != null)
entry.handleDidPopNext(poppelementsedRoute);
poppedRoute = entry.route;
}
entry.handlePios最好玩的手游op(
navigator: this,
previousPresent: _getRouteBef复杂度剖析ore(index, _RouteEntiOSry.willBePresentPredicate)?.复杂度调整因子route,
);
assert(entry.currentState == _RouteLifecycle.popping);
canRemoveOrAdd = true;
break;
case _RouteLifecycle.popping:
// Will exit复杂度最高的是 this state when animation comios15beta2pletes.
break;
case _RouteLifecycle.dispose:
// Delay dispelementary schoolosal uflutter中文官网ntil didChangeNext/didChangePrevious have been sent.
toBeDisposed.add(_history.removeAt(index));
entry = next;
break;
case _RouteLifecycle.disposed:
case _RouteLifecycle.staging:
assert(false);
break;
}
index -= 1;
next = entry;
entry = previous;
previous = in复杂度o(1)什么意思dex > 0 ? _hist复杂度排序ory[i复杂度英文ndex - 1] :flutter结构优缺点 null;
}
// ...
}

handlePoflutter结构优缺点p 将状况切换到 poping(动画实ios15行进程),然后宣布告知,而 poping 状况不作处理,由于这是一个过渡状况,在动画实施完之后会主动切换到 dispose 状况,相同的,上面的 pushing 状况也是,而在 dispose 分支中,便是将 _RouteEntry 从 _复杂度怎样核算的history 移除并参与到 toBeDisposed,然后elementui在遍历完毕之后统一毁掉。

remove

remove 的逻辑便是先从 _history 中找到一个跟传进来的一起的 _RouteEntryandroid的drawable类,将它的状况设为 remvoe,再调用 _flushHis复杂度怎样核算的toryUpdates。

void _flushHistory复杂度怎样核算的Updates({bool rearrangeOverlay = true}) {
// ...
while (index >= 0) {ios模拟器
switch (entry.currentState) {
// ...
case _RouteLifecycle.remove:
if (!seenTopActiveRoute) {
if (poppedRoute != null)
entry.route.didPopNext(poAndroidppedRoute);
poppedRoute = nulios体系l;
}
entry.handleRemoElementval(
navigator: this,
previousPresent:flutter值得学吗 _getRouteBefore(index, _RouteEntry.willBePresentPredicaelementste)?.route复杂度最优,
);
assert(entry.currentState == _RouteLifecycle.removing);
continue;
case _RouteLifecycle.remoiOSving:
if (!canRemoveO复杂度最高的是rAdd && next != null) {
// We aren't allowed to remove this route yeandroid什么意思t.
bFlutterreak;
}
entry.currentState = _RouteLifecycle.dispose;
continue;
case _RouteLifecycle.dispose:
// Delay dispoandroid手机sal until didChangeNext/didChangePelementary是什么意思revious have been senflutter值得学吗t.
toBeDisposed.add(_histo复杂度最高的是ryflutter结构优缺点.removeAt(index));
entry = next;
break;
case _RouteLifecycle.disposed:
case _RouteLandroid下载ifecycle.standroid下载装置aging:
assert(falelements是什么牌子se);
break;
}
index -= 1;
next = entry;
entry = previous;
preios模拟器vious = index > 0 ? _history[index - 1]Element : null;
}
// ...
}

首要会调用 handleRemelementary schooloval,调用告知复杂度最优,并将状况切换到 rem复杂度o(1)什么意思oving,在 removing 阶段再将状况切到 dispose,然后便是将其参与android下载装置 toBeDisposed,所以整个进程中是不触及动画的,一般只用来移出非正在展现的页面,不然仍是举荐用 pandroid下载op。

总结

以上是路由机制的完毕原理,就其全flutter结构优缺点体而言,最给人耳目一新的便是状况处理的参与,经过将一个页面的进出区分到不同状况处理,是能够有效降低代码的复杂度elementanimation的,不过从现在的作用android下载装置来看,这一个进程实施的还不可精粹,比方状况的区分不可合理,从这些状况的规划来看,add/push/pop 都有对应的 ing 方式标明正在实施中,可是 adding 的存在我暂时没有看到必要性,还有便是感觉代码的组织上仍是有点问题,比方 handleAdd 与 handPush 实践上还有很大部分的代码重复的,这部分不知道今后会不会优化。

其他还有一点感觉做的不到位,复杂度o便是 _routeNamed 这个函数没有对外开放,而且并不是全部的路由操作都供给了 name 为入参的包装,比方 removeRoute,在这种状况下就无法很便当的Android调用。