Flutter 路由管理

Flutter 中,通常我们使用 Navigator 来管理全局的页面路由,在整个应用中维护一个路由堆栈。但是,有些情况下你可能需要一个局部路由,也就是在应用的某个部分内部维护一个独立的路由堆栈,而不影响全局路由。为了实现这一点,你可以在你的应用中创建一个新的 Navigator
定义了局部路由之后,不能随便使用 Navigator.of(context),你需要确保使用的 context 是正确的。当你调用 Navigator.of(context) 时,Flutter 会从当前的 context 开始向上遍历 widget 树,直到找到最近的 Navigator。如果你没有特别指定,它可能会默认找到全局的 Navigator。

如何确保使用的是局部路由的 Navigator:

  • 确保你传递给 Navigator 的 context 是局部 Navigator 下面的 widget 的 context。
  • 如果局部 Navigator 有一个 key,你可以使用这个 key 来获取 NavigatorState,然后进行操作,如 GlobalKey().currentState.push(...)。

局部路由简单使用

  1. 代码
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: AppHome()));
}

class AppHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('局部 Navigator 示例')),
      body: Container(
        // 给局部路由设置一个唯一的 key
        child: Navigator(
          key: GlobalKey<NavigatorState>(),
          // 定义局部路由的页面
          onGenerateRoute: (RouteSettings settings) {
            WidgetBuilder builder;
            switch (settings.name) {
              case '/':
                builder = (BuildContext context) => FirstScreen();
                break;
              case '/second':
                builder = (BuildContext context) => SecondScreen();
                break;
              default:
                throw Exception('Invalid route: ${settings.name}');
            }
            return MaterialPageRoute(builder: builder, settings: settings);
          },
        ),
      ),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        child: Text('打开第二页'),
        onPressed: () {
          // 使用局部 Navigator 进行页面跳转
          Navigator.of(context).pushNamed('/second');
        },
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 这里的第二个界面使用 Scaffold 才能在左上角显示返回的角标,其实就是显示在appBar的这里 
      appBar: AppBar(title: Text('第二页')),
      body: Center(
        child: ElevatedButton(
          child: Text('返回第一页'),
          onPressed: () {
            // 使用局部 Navigator 返回到上一页
            Navigator.of(context).pop();
          },
        ),
      ),
    );
  }
}
  1. 效果
  • 第一页效果
  • 点击第二页效果