The Navigation between Flutter Routes
Navigation 纵览
容易想象到的是,客户端的导航逻辑具有相似性。对具有原生app经验的开发者来说,它可以类比于 native app 开发中的“页面”跳转(Android 中的 Activity, iOS 中的 ViewController)。同样UI层面的概念在Flutter也出现了,它就是 Route其关联的有Widget, 较为常见的Widget有 StatelessWidget 或是 StatefulWidget ;同时与跳转逻辑相关的还有Navigator, 而 Navigator 本身也是一个Widget (Flutter中 Widget无处不在!😊),它遵循Stack栈的规则管理着一系列子Widget。
最直接的页面跳转方式
使用 MaterialPageRoute :
Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => YourWidget()),
  );
Route 利用一个builder方法定义自身的Widget,而非直接传入一个子Widget, 这是因为基于自身被Pushed 或是 Popped的不同context环境下,它会被构建以及重建(built and rebuilt)。
具名的 Route
手机上的App通常会有大量的Route, 而通过名字去找到相应的Route往往也更容易。按照约定Route的名字和路径的表示(path-like structure)比较相像。"/" 用以表示 App 的Home页面的Route。
MaterialApp 在创建的时候可以指定其 routes (结构为 Map<String, WidgetBuilder>),它保留了 Route的名字与 创建对应Widget build 方法的映射关系。
 MaterialApp(
   home: MyAppHome(), // becomes the route named '/'
   routes:   {
     '/a_route_name': (BuildContext context) => YourWidget(),
   },
 )
按名字显示一个Route :
Navigator.pushNamed(context, '/a_route_name');
参数传递
设置传入参数
同样使用 MaterialPageRoute,可以设置其可选参数settings 传入参数:
MaterialPageRoute(
  builder: (BuildContext context) {
    return YourWidget();
  },
  settings: RouteSettings(arguments: your_param_object),
);
对于具名的Route,类似的方法有:
Navigator.pushNamed(context, routeName, arguments: your_param_object);
读取传入的参数
class MyWidget {
  @override
  Widget build(BuildContext context) {
    final MyArgs args = ModalRoute.of(context).settings.arguments;
    // ...
  }
}
设置传出的参数
在第2个Widget中 (SelectionScreen) 设定返回值
Navigator.pop(context, 'Yep!');
在首个Widget中接收:
_navigateAndDisplaySelection(BuildContext context) async {
  final result = await Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SelectionScreen()),
  );
  // After the Selection Screen returns a result, hide any previous snackbars
  // and show the new result.
  Scaffold.of(context)
    ..removeCurrentSnackBar()
    ..showSnackBar(SnackBar(content: Text("$result")));
}
更多 Navigation 相关的方法
Navigator.popAndPushNamed(context, routeName);Navigator.of(context).pushNamedAndRemoveUntil(HomeScreen.routeName, (_) => false);Navigator.of(context).pushReplacement(newRoute)