https://gitee.com/frontend-qin/getx/blob/master/documentation/zh_CN/route_management.md
路由管理
這是關(guān)于Getx在路由管理方面的完整解釋柳洋。
如何使用
將此添加到你的pubspec.yaml文件中正卧。
dependencies:
get:
如果你要在沒有context的情況下使用路由/SnackBars/Dialogs/BottomSheets颜阐,或者使用高級的Get API,你只需要在你的MaterialApp前面加上 "Get"掉丽,就可以把它變成GetMaterialApp跌榔,享受吧!
GetMaterialApp( // Before: MaterialApp(
home: MyHome(),
)
普通路由導(dǎo)航
導(dǎo)航到新的頁面。
Get.to(NextScreen());
關(guān)閉SnackBars捶障、Dialogs僧须、BottomSheets或任何你通常會用Navigator.pop(context)關(guān)閉的東西。
Get.back();
進入下一個頁面残邀,但沒有返回上一個頁面的選項(用于SplashScreens皆辽,登錄頁面等)。
Get.off(NextScreen());
進入下一個界面并取消之前的所有路由(在購物車芥挣、投票和測試中很有用)驱闷。
Get.offAll(NextScreen());
要導(dǎo)航到下一條路由,并在返回后立即接收或更新數(shù)據(jù)空免。
var data = await Get.to(Payment());
在另一個頁面上空另,發(fā)送前一個路由的數(shù)據(jù)。
Get.back(result: 'success');
并使用它蹋砚,例:
if(data == 'success') madeAnything();
你不想學(xué)習(xí)我們的語法嗎扼菠?
只要把 Navigator(大寫)改成 navigator(小寫)摄杂,你就可以擁有標準導(dǎo)航的所有功能,而不需要使用context循榆,例如:
// 默認的Flutter導(dǎo)航
Navigator.of(context).push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return HomePage();
},
),
);
// 使用Flutter語法獲得析恢,而不需要context。
navigator.push(
MaterialPageRoute(
builder: (_) {
return HomePage();
},
),
);
// get語法 (這要好得多)
Get.to(HomePage());
別名路由導(dǎo)航
- 如果你喜歡用別名路由導(dǎo)航秧饮,Get也支持映挂。
導(dǎo)航到下一個頁面
Get.toNamed("/NextScreen");
瀏覽并刪除前一個頁面。
Get.offNamed("/NextScreen");
瀏覽并刪除所有以前的頁面盗尸。
Get.offAllNamed("/NextScreen");
要定義路由柑船,使用GetMaterialApp。
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.zoom
),
],
)
);
}
要處理到未定義路線的導(dǎo)航(404錯誤)泼各,可以在GetMaterialApp中定義unknownRoute頁面鞍时。
void main() {
runApp(
GetMaterialApp(
unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
],
)
);
}
發(fā)送數(shù)據(jù)到別名路由
只要發(fā)送你想要的參數(shù)即可。Get在這里接受任何東西扣蜻,無論是一個字符串逆巍,一個Map,一個List莽使,甚至一個類的實例蒸苇。
Get.toNamed("/NextScreen", arguments: 'Get is the best');
在你的類或控制器上:
print(Get.arguments);
//print out: Get is the best
動態(tài)網(wǎng)頁鏈接
Get提供高級動態(tài)URL,就像在Web上一樣吮旅。Web開發(fā)者可能已經(jīng)在Flutter上想要這個功能了,Get也解決了這個問題味咳。
Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
在你的controller/bloc/stateful/stateless類上:
print(Get.parameters['id']);
// out: 354
print(Get.parameters['name']);
// out: Enzo
你也可以用Get輕松接收NamedParameters庇勃。
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => MyHomePage(),
),
GetPage(
name: '/profile/',
page: () => MyProfile(),
),
//你可以為有參數(shù)的路由定義一個不同的頁面,也可以為沒有參數(shù)的路由定義一個不同的頁面槽驶,但是你必須在不接收參數(shù)的路由上使用斜杠"/"责嚷,就像上面說的那樣。
GetPage(
name: '/profile/:user',
page: () => UserProfile(),
),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.cupertino
),
],
)
);
}
發(fā)送別名路由數(shù)據(jù)
Get.toNamed("/second/34954");
在第二個頁面上掂铐,通過參數(shù)獲取數(shù)據(jù)
print(Get.parameters['user']);
// out: 34954
或像這樣發(fā)送多個參數(shù)
Get.toNamed("/profile/34954?flag=true");
在第二個屏幕上罕拂,通常按參數(shù)獲取數(shù)據(jù)
print(Get.parameters['user']);
print(Get.parameters['flag']);
// out: 34954 true
現(xiàn)在,你需要做的就是使用Get.toNamed()來導(dǎo)航你的別名路由全陨,不需要任何context(你可以直接從你的BLoC或Controller類中調(diào)用你的路由)爆班,當你的應(yīng)用程序被編譯到web時,你的路由將出現(xiàn)在URL中辱姨。
中間件
如果你想通過監(jiān)聽Get事件來觸發(fā)動作柿菩,你可以使用routingCallback來實現(xiàn)。
GetMaterialApp(
routingCallback: (routing) {
if(routing.current == '/second'){
openAds();
}
}
)
如果你沒有使用GetMaterialApp雨涛,你可以使用手動API來附加Middleware觀察器枢舶。
void main() {
runApp(
MaterialApp(
onGenerateRoute: Router.generateRoute,
initialRoute: "/",
navigatorKey: Get.key,
navigatorObservers: [
GetObserver(MiddleWare.observer), // HERE !!!
],
),
);
}
創(chuàng)建一個MiddleWare類
class MiddleWare {
static observer(Routing routing) {
///你除了可以監(jiān)聽路由外懦胞,還可以監(jiān)聽每個頁面上的SnackBars、Dialogs和Bottomsheets凉泄。
if (routing.current == '/second' && !routing.isSnackbar) {
Get.snackbar("Hi", "You are on second route");
} else if (routing.current =='/third'){
print('last route called');
}
}
}
現(xiàn)在躏尉,在你的代碼上使用Get:
class First extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.add),
onPressed: () {
Get.snackbar("hi", "i am a modern snackbar");
},
),
title: Text('First Route'),
),
body: Center(
child: ElevatedButton(
child: Text('Open route'),
onPressed: () {
Get.toNamed("/second");
},
),
),
);
}
}
class Second extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.add),
onPressed: () {
Get.snackbar("hi", "i am a modern snackbar");
},
),
title: Text('second Route'),
),
body: Center(
child: ElevatedButton(
child: Text('Open route'),
onPressed: () {
Get.toNamed("/third");
},
),
),
);
}
}
class Third extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Third Route"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Get.back();
},
child: Text('Go back!'),
),
),
);
}
}
免context導(dǎo)航
SnackBars
用Flutter創(chuàng)建一個簡單的SnackBar,你必須獲得Scaffold的context后众,或者你必須使用一個GlobalKey附加到你的Scaffold上胀糜。
final snackBar = SnackBar(
content: Text('Hi!'),
action: SnackBarAction(
label: 'I am a old and ugly snackbar :(',
onPressed: (){}
),
);
// 在小組件樹中找到腳手架并使用它顯示一個SnackBars。
Scaffold.of(context).showSnackBar(snackBar);
用Get:
Get.snackbar('Hi', 'i am a modern snackbar');
有了Get吼具,你所要做的就是在你代碼的任何地方調(diào)用你的Get.snackbar僚纷,或者按照你的意愿定制它。
Get.snackbar(
"Hey i'm a Get SnackBar!", // title
"It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", // message
icon: Icon(Icons.alarm),
shouldIconPulse: true,
onTap:(){},
barBlur: 20,
isDismissible: true,
duration: Duration(seconds: 3),
);
////////// ALL FEATURES //////////
// Color colorText,
// Duration duration,
// SnackPosition snackPosition,
// Widget titleText,
// Widget messageText,
// bool instantInit,
// Widget icon,
// bool shouldIconPulse,
// double maxWidth,
// EdgeInsets margin,
// EdgeInsets padding,
// double borderRadius,
// Color borderColor,
// double borderWidth,
// Color backgroundColor,
// Color leftBarIndicatorColor,
// List<BoxShadow> boxShadows,
// Gradient backgroundGradient,
// TextButton mainButton,
// OnTap onTap,
// bool isDismissible,
// bool showProgressIndicator,
// AnimationController progressIndicatorController,
// Color progressIndicatorBackgroundColor,
// Animation<Color> progressIndicatorValueColor,
// SnackStyle snackStyle,
// Curve forwardAnimationCurve,
// Curve reverseAnimationCurve,
// Duration animationDuration,
// double barBlur,
// double overlayBlur,
// Color overlayColor,
// Form userInputForm
///////////////////////////////////
如果您喜歡傳統(tǒng)的SnackBars拗盒,或者想從頭開始定制怖竭,包括只添加一行(Get.snackbar使用了一個強制性的標題和信息),您可以使用
Get.rawSnackbar();
它提供了建立Get.snackbar的RAW API陡蝇。
Dialogs
打開Dialogs:
Get.dialog(YourDialogWidget());
打開默認Dialogs:
Get.defaultDialog(
onConfirm: () => print("Ok"),
middleText: "Dialog made in 3 lines of code"
);
你也可以用Get.generalDialog代替showGeneralDialog痊臭。
對于所有其他的FlutterDialogs小部件,包括cupertinos登夫,你可以使用Get.overlayContext來代替context广匙,并在你的代碼中任何地方打開它。
對于不使用Overlay的小組件恼策,你可以使用Get.context鸦致。
這兩個context在99%的情況下都可以代替你的UIcontext,除了在沒有導(dǎo)航context的情況下使用 inheritedWidget的情況涣楷。
BottomSheets
Get.bottomSheet類似于showModalBottomSheet分唾,但不需要context:
Get.bottomSheet(
Container(
child: Wrap(
children: <Widget>[
ListTile(
leading: Icon(Icons.music_note),
title: Text('Music'),
onTap: () {}
),
ListTile(
leading: Icon(Icons.videocam),
title: Text('Video'),
onTap: () {},
),
],
),
)
);
嵌套導(dǎo)航
Get讓Flutter的嵌套導(dǎo)航更加簡單。
你不需要context狮斗,而是通過Id找到你的導(dǎo)航棧绽乔。
- 注意:創(chuàng)建平行導(dǎo)航堆棧可能是危險的碳褒。理想的情況是不要使用NestedNavigators折砸,或者盡量少用。如果你的項目需要它沙峻,請繼續(xù)睦授,但請記住,在內(nèi)存中保持多個導(dǎo)航堆椬ㄐ铮可能不是一個好主意(消耗RAM)睹逃。
看看它有多簡單:
Navigator(
key: Get.nestedKey(1), // create a key by index
initialRoute: '/',
onGenerateRoute: (settings) {
if (settings.name == '/') {
return GetPageRoute(
page: () => Scaffold(
appBar: AppBar(
title: Text("Main"),
),
body: Center(
child: TextButton(
color: Colors.blue,
onPressed: () {
Get.toNamed('/second', id:1); // navigate by your nested route by index
},
child: Text("Go to second"),
),
),
),
);
} else if (settings.name == '/second') {
return GetPageRoute(
page: () => Center(
child: Scaffold(
appBar: AppBar(
title: Text("Main"),
),
body: Center(
child: Text("second")
),
),
),
);
}
}
),