1 基础知识
在了解Flutter的路由管理功能前,首先需要几个基础类有一定熟悉,以下简单介绍路由相关几个类的功能。
| 类 | 功能 |
|---|---|
| Navigator | 导航器,管理路由的Widget |
| Route及子类 | 用于Navigator管理的页面 |
| RouteSettings及子类 | 保存页面配置信息,如name,arguments等 |
2 路由管理Navigator.push
管理Flutter路由分为两种方式:
- 直接路由
- 命名路由
| 路由方式 | 实现方式 |
|---|---|
| 直接路由 | Navigator.push调用,使用Route进行路由 |
| 命名路由 | Navigator.pushNamed调用,使用routeName进行路由 |
2.1 直接路由
2.1.1 源码
@optionalTypeArgs
static Future<T?> push<T extends Object?>(BuildContext context, Route<T> route) {
return Navigator.of(context).push(route);
}
2.1.2 使用演示
从TestHomePage页面路由到TestRouterPage。
class TestHomePage extends StatelessWidget {
const TestHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
ScreenUtil.init(context, designSize: const Size(375, 667));
return Scaffold(
body: GestureDetector(
child: Center(
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(border: Border.all(width: 1, color: Colors.red)),
child: const Text("This is a home page. This is a home page. This is a home page.",
textAlign: TextAlign.center, style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: Colors.red)),
),
),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const TestRouterPage();
}));
// Navigator.pushNamed(context, TestRouterPage.routeName);
},
),
);
}
}
class TestRouterPage extends StatelessWidget {
const TestRouterPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(border: Border.all(width: 1, color: Colors.blue)),
child: const Text("This is a router page. ",
textAlign: TextAlign.center, style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: Colors.blue)),
),
),
);
}
}
2.2 命名路由
2.2.1 源码
@optionalTypeArgs
static Future<T?> pushNamed<T extends Object?>(
BuildContext context,
String routeName, {
Object? arguments,
}) {
return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
}
2.2.2 配置使用
s1.通用路由配置类
class TestRouter {
// 此处用于后续通用路由配置
static Map<String, Function> routes = {
TestRouterPage.routeName: (context) => const TestRouterPage(),
};
// 配置到MaterialApp的onGenerateRoute中
var onGenerateRoute = (RouteSettings settings) {
final String? name = settings.name;
final Function? pageBuilder = routes[name];
if (pageBuilder != null) {
if (settings.arguments != null) {
// 带参数路由
final Route route = MaterialPageRoute(builder: (context) => pageBuilder(context), settings: settings);
return route;
} else {
// 无参数路由
final Route route = MaterialPageRoute(builder: (context) => pageBuilder(context));
return route;
}
}
return MaterialPageRoute(builder: (context) => WebPage(const Page404()));
};
}
s2.路由配置类加到APP启动的MaterialApp的onGenerateRoute中
class TestApp extends StatelessWidget {
const TestApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primaryColor: Colors.blue, primaryTextTheme: TextTheme()),
onGenerateRoute: TestRouter().onGenerateRoute,
home: const TestHomePage(),
);
}
}
2.2.3 使用演示
Navigator.pushNamed(context, TestRouterPage.routeName);
3 路由管理Navigator.pop
3.1 源码
@optionalTypeArgs
static void pop<T extends Object?>(BuildContext context, [ T? result ]) {
Navigator.of(context).pop<T>(result);
}
3.2 使用演示
从TestRouterConstructPage页面后退到TestHomePage。
class TestRouterConstructPage extends StatelessWidget {
late Map _argu;
TestRouterConstructPage(this._argu, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Center(
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(border: Border.all(width: 1, color: Colors.blue)),
child: Text(
"This is a router construct page. argMap = $_argu",
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: Colors.blue),
),
)),
onTap: () {
Navigator.pop(context);
},
),
);
}
}
4 Navigator.popUntil
4.1 源码
static void popUntil(BuildContext context, RoutePredicate predicate) {
Navigator.of(context).popUntil(predicate);
}
4.2 使用演示
从TestRouterConstructPage页面后退到首页【TestHomePage】。
class TestRouterConstructPage extends StatelessWidget {
late Map _argu;
TestRouterConstructPage(this._argu, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Center(
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(border: Border.all(width: 1, color: Colors.blue)),
child: Text(
"This is a router construct page. argMap = $_argu",
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: Colors.blue),
),
)),
onTap: () {
Navigator.popUntil(context, (route) => route.isFirst);
},
),
);
}
}
跳转指定页
// 页面push跳转
Navigator.push(context, MaterialPageRoute(settings: const RouteSettings(name: "/TestHomePage"), builder: (context) => TestHomePage()));
// 页面pop跳转
Navigator.popUntil(context, ModalRoute.withName("/TestHomePage")),
关于路由及Navigator.push和Navigator.pop的参数处理部分在下一节中继续详细说明。