[TOC]
前言
Route (路由)
Router (路由管理器)
將一個(gè)URL路徑和一個(gè)函數(shù)映射
/users -> getAllUsers()
/users/count -> getUsersCount()
或者將一個(gè)頁面和方法映射
getHome()=> homePage.index
在Flutter中是將一個(gè)字符串和一個(gè)方法(或者說page)映射
"homePage" -> new HomePage()
靜態(tài)路由
靜態(tài)路由就是通過字符串進(jìn)行注冊的路由
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter實(shí)例'),
routes: <String, WidgetBuilder> {
// 這里可以定義靜態(tài)路由,不能傳遞參數(shù)
'/router/second': (_) => new SecondPage(),
'/router/home': (_) => new RouterHomePage(),
},
);
使用
push一個(gè)新頁面,pushNamed方法是有一個(gè)Future的返回值的,所以靜態(tài)路由也是可以接收下一個(gè)頁面的返回值的。但是不能向下一個(gè)頁面?zhèn)鬟f參數(shù)。
Navigator.of(context).pushNamed('/router/second');
// 帶返回值
Navigator.of(context).pushNamed('/router/second').then((value) {
// dialog顯示返回值
_showDialog(context, value);
})
pop回上一個(gè)頁面
Navigator.of(context).pop('這個(gè)是要返回給上一個(gè)頁面的數(shù)據(jù)');
動(dòng)態(tài)路由的使用
當(dāng)需要向下一個(gè)頁面?zhèn)鬟f參數(shù)時(shí),要用到所謂的動(dòng)態(tài)路由,自己生成頁面對象,所以可以傳遞自己想要的參數(shù)。
Navigator.of(context).push(new MaterialPageRoute(builder: (_) {
return new SecondPage(title: '路由是個(gè)好東西,要進(jìn)一步封裝');
}));
也可以用PageRouterBuilder來自定義打開動(dòng)畫
Navigator.of(context).push(new PageRouteBuilder(pageBuilder:
(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return new RefreshIndicatorDemo();
}, transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
// 添加一個(gè)平移動(dòng)畫
return BRouter.createTransition(animation, child);
}));
平移的變換
/// 創(chuàng)建一個(gè)平移變換
/// 跳轉(zhuǎn)過去查看源代碼,可以看到有各種各樣定義好的變換
static SlideTransition createTransition(
Animation<double> animation, Widget child) {
return new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: const Offset(0.0, 0.0),
).animate(animation),
child: child, // child is the value returned by pageBuilder
);
}
Page(控制器)的入棧和出棧和刷新。
以下是Flutter出棧和入棧的方法,共計(jì)13種,當(dāng)然也有直接是Navigator.push 之類的對照方法共計(jì)13種,他們沒什么區(qū)別,
因?yàn)镹avigator.method()這些方法其實(shí)也是調(diào)用下面的方法實(shí)現(xiàn)的。
********************
Navigator.of(context).pushReplacement(newRoute);
Navigator.of(context).push(route);
Navigator.of(context).pushReplacementNamed(routeName);
Navigator.of(context).pushNamed(routeName);
Navigator.of(context).pushNamedAndRemoveUntil(newRouteName, predicate)
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed(routeName);
Navigator.of(context).popUntil(predicate);
Navigator.of(context).maybePop();
Navigator.of(context).removeRouteBelow(anchorRoute);
Navigator.of(context).removeRoute(route);
Navigator.of(context).replace(oldRoute: null, newRoute: null);
Navigator.of(context).replaceRouteBelow(anchorRoute: null);
Navigator.of(context).push();
官方的給的demo
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) => MyPage()));
1、適用非靜態(tài)路由進(jìn)行跳轉(zhuǎn)。
2、傳遞參數(shù)只能通過控制器的構(gòu)造進(jìn)行傳遞。
Navigator.of(context).pushNamed(context,routeName,args)
類似上面的push方法,不過只能打開靜態(tài)Route,可以通過args傳遞參數(shù)。

D7F05CA1-3770-4CD9-A1CA-A666D92A4740.png
Navigator.of(context).pushNamedAndRemoveUntil(newRouteName, predicate)

87D3DCF4-60EC-4A38-9C3F-4C353BFA6807.png
flutter 默認(rèn)有兩種路由(靜態(tài)路由和動(dòng)態(tài)路由)
對應(yīng)的RouterName也有兩種方式進(jìn)行申明,
* 靜態(tài)路由在注冊的時(shí)候就進(jìn)行了申明,默認(rèn)MainPager 為(“/”)
* 動(dòng)態(tài)路由是當(dāng)你打開這個(gè)Route的進(jìn)行設(shè)置的(RouteSettings.name="pagerName")
上面圖示采用以下方式就行打開頁面
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (BuildContext context) {
return CPager();
}), ModalRoute.withName("pagerA"));
1 :左1為操作流程,左二為結(jié)果:可以發(fā)現(xiàn) A_Pager&B_Pager都被結(jié)束掉了,直到碰到MainPage 也就是默認(rèn)routName為"/"的主界面。
2 :右2為操作流程,右1為結(jié)果, B-Pager被結(jié)束掉了,知道碰到的routeName為pageA的界面。
所以這個(gè)push方法的作用就是打開一個(gè)新界面,并且結(jié)束掉之后的界面,直到碰到指定RoutName的Pager為止,如果一個(gè)都沒有匹配到,就會(huì)結(jié)束所有pager除了新打開的這個(gè)Pager.
Navigator.of(context).pushReplacement(newRoute,To result)

F55C7B67-C326-4417-AA65-DDCD619A0F73.png
!、pushReplacement 這個(gè)很好理解,就是Push的Pager替換當(dāng)前Pager,可以是新的界面,也可以是刷新當(dāng)前界面。
注意這里的To result 其實(shí)這個(gè)意思就是返回給上一個(gè)route(當(dāng)前正被替換的route的開啟者)的一個(gè)結(jié)果,官網(wǎng)文檔表明這是為了彈出框或者選擇框被消失,并進(jìn)入下一個(gè)界面,需要將結(jié)果返回上一個(gè)界面可以進(jìn)行的操作。
If non-null, `result` will be used as the result of the route that is
popped; the future that had been returned from pushing the popped route
will complete with `result`. Routes such as dialogs or popup menus
typically use this mechanism to return the value selected by the user to
the widget that created their route. The type of `result`, if provided,
must match the type argument of the class of the popped route (`TO`).
Navigator.pop(context)
關(guān)閉一個(gè)路由,這里可以是Route也可以是Dialog, pop都是可以向上一層返回?cái)?shù)據(jù)的。
Navigator.of(context).popAndPushNamed(routeName);
Navigator.of(context).popUntil(predicate);
參考以上push
Navigator.of(context).mayPop(content);
這個(gè)Android 開發(fā)者很好理解,這個(gè)就是喚醒了一個(gè)Android返回物理鍵,如果當(dāng)前route 沒有WillPopScope()進(jìn)行包裹(也即是攔截物理返回鍵&navigatorBar返回鍵),他就結(jié)束當(dāng)前route。如果進(jìn)行了包裹,就不結(jié)束當(dāng)前界面。
Navigator.of(context).removeRouteBelow(anchorRoute);
Navigator.of(context).removeRoute(route);
這個(gè)兩個(gè)一般用不到,官方說法
removeRoute:
This method is used, for example, to instantly dismiss dropdown menus that
are up when the screen's orientation changes.
也就是說移除當(dāng)前Route上的彈出框,我測試的時(shí)候,是用EvenBus方法在B-Pager中點(diǎn)擊觸發(fā)event,在A-Pager中移除了B-Pager,其實(shí)這個(gè)用到的地方就是你必須持有對應(yīng)要移除的路由Instant.
removeRouteBelow: 就是移除指定路由底層的臨近的一個(gè)路由,當(dāng)對應(yīng)路由不存在的時(shí)候會(huì)報(bào)錯(cuò)。
Navigator.replace(context, oldRoute: null, newRoute: null)
Navigator.replaceRouteBelow();
這個(gè)兩個(gè)方法也必須持有oldRoute的Instant,目的就是替換對應(yīng)的路由。
官方說法是為了構(gòu)建非線型用戶體驗(yàn),這個(gè)說法就是針對線型Android開發(fā)人員熟悉的APager->BPager->CPager
然后返回就是 CPager->BPager->APager
通常之前Android面試:會(huì)問到你一個(gè)常見的問題,如果控制幾個(gè)Activty流程用來達(dá)到業(yè)務(wù)流程的目的,用上Flutter 你會(huì)發(fā)現(xiàn)這些很簡單就能實(shí)現(xiàn)了,而不必要進(jìn)行維護(hù)一個(gè)ActivityStack,或者通過Actity生命周期進(jìn)行攔截的復(fù)雜方式。