flutter 开发技巧:路由

104 阅读3分钟

背景:管理多个⻚⾯时有两个核⼼概念和类:Route 和 Navigator。 ⼀个 route 是⼀个屏幕或⻚⾯的抽象,Navigator 是管理 route 的 Widget。Navigator 可以通过 route ⼊栈和出栈来实现⻚⾯之间的跳转。

Navigator 提供了⼀系列⽅法来管理路由栈,其中最常⽤的两个⽅法是push()和pop(),它们的含义如下。

  • push():将给定的路由⼊栈,返回值是⼀个Future对象,⽤以接收路由出栈时的返回数据。
  • pop():将栈顶路由出栈,返回结果为⻚⾯关闭时返回给上⼀个⻚⾯的数据。

匿名路由

基本⽤法仅适⽤于⻚⾯较少的场景。

具体代码实现:


// 跳转:

Navigator.push()

// 退出:

Navigator.pop()


具体代码实现:


import 'package:flutter/material.dart';

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

title: 'Flutter Demo',

home: Home(),

debugShowCheckedModeBanner: false, );

}

}

class Home extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('⾸⻚'),

),

body: Center(

child: RaisedButton(

child: Text('跳转到商品⻚'),

onPressed: () => Navigator.push(

context,

MaterialPageRoute(builder: (context) => Product())

)),),);}}



class Product extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('商品⻚'),

),

body: Center(

child: RaisedButton(

child: Text('返回⾸⻚'),

onPressed: () => Navigator.pop(context)

),),);}

跳转⻚⾯使⽤的是 Navigator.push() ⽅法,该⽅法可以将⼀个新的路由添加到由 Navigator 管理的路由对象 的栈顶。⽽创建新的路由对象使⽤的是 MaterialPageRoute,MaterialPageRoute 是 PageRoute 的⼦类,定义了路由创建及切换时过渡动画的相关接⼝及属性。

命名路由

所谓命名路由,就是给⻚⾯起⼀个别名,然后使⽤⻚⾯的别名就可以打开它,使⽤此种⽅式来管理路由,使得路由的管理更加清晰直观。 要想通过别名来指定⻚⾯切换,必须先给应⽤程序 MaterialApp 提供⼀个⻚⾯名称映射规则,即路由表。路由表是⼀个Map的结构,其中key对应⻚⾯名字,value则是对应的⻚⾯,如下所示:


MaterialApp(

// ... // 其他配置

routes:{ // 注册路由(路由表)

'first': (context) => FirstPage(),

'second': (context) => SecondPage(),

},

initialRoute: 'first', // 初始路由⻚⾯

);

使⽤命名路由

// 跳转
Navigator.pushNamed(context, 'second'); // second 表示⻚⾯别名
// 返回
Navigator.pop(context);

未知路由

如果打开⼀个不存在的路由⻚⾯。可以跳转到⼀个统⼀的错误⻚⾯(相当于 Web 端的 404)。在注册路由表时, Flutter 提供了⼀个 UnknownRoute 属性,⽤来对未知的路由标识符,进⾏统⼀的⻚⾯跳转处理,如下所示:


MaterialApp(

// ... // 其他配置

routes:{},

onUnknownRoute: (RouteSettings setting) => MaterialPageRoute(builder: (context) =>

UnknownPage()), // 错误路由处理,返回UnknownPage

);

class UnknownPage extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('404'),

),

body: Center(

child: Text('未知⻚⾯')

),

);

}

}

动态路由 动态路由是指通过 onGenerateRoute 属性指定的路由,可以根据访问路径进⾏动态匹配和拦截。


class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

// 通过 onGenerateRoute ⽣成动态路由

onGenerateRoute: (settings) {

// Handle '/'

if (settings.name == '/') {

return MaterialPageRoute(builder: (context) => HomeScreen());

}

// Handle '/details/:id'

var uri = Uri.parse(settings.name);

if (uri.pathSegments.length == 2 &&

uri.pathSegments.first == 'details') {

var id = uri.pathSegments[1];

return MaterialPageRoute(builder: (context) => DetailScreen(id: id));

}

return MaterialPageRoute(builder: (context) => UnknownScreen());

},

);

}

}

路由传参

//普通路由传参
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return BlogDetail(id: blogItem['id'],);
}));

//接收参数
class BlogDetail extends StatefulWidget {
// 构造函数
BlogDetail({Key key, @required this.id}) : super(key: key);
final int id;
}

//命名路由传参
Navigator.pushNamed(
context,"/homePage",arguments: {'title': "命令路由传递过来的title"}
);

//接收参数
class HomePage extends StatelessWidget {
final Map arguments;
HomePage({Key key, this.arguments});
String title = arguments['title'];
// ......
}