MST

星途 面试题库

面试题:Flutter Navigator 中如何实现嵌套导航及处理导航状态

在一个复杂的 Flutter 应用中,可能存在多个嵌套的 Navigator 场景。请阐述如何在 Flutter 中正确实现嵌套导航,并且说明如何有效地管理和处理不同层级 Navigator 的导航状态,例如如何在子 Navigator 中影响父 Navigator 的状态等,提供具体的代码实现思路和关键代码片段。
37.0万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

实现嵌套导航

  1. 创建嵌套 Navigator
    • 在 Flutter 中,可以通过在 Widget 树中嵌套 Navigator 组件来实现嵌套导航。例如,假设我们有一个主 Navigator,然后在某个页面中需要一个子 Navigator
    • 首先定义主 Navigator,通常在 MaterialAppCupertinoApp 中:
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainNavigator(),
    );
  }
}

class MainNavigator extends StatefulWidget {
  @override
  State<MainNavigator> createState() => _MainNavigatorState();
}

class _MainNavigatorState extends State<MainNavigator> {
  @override
  Widget build(BuildContext context) {
    return Navigator(
      initialRoute: '/',
      onGenerateRoute: (settings) {
        switch (settings.name) {
          case '/':
            return MaterialPageRoute(builder: (context) => const HomePage());
          case '/page1':
            return MaterialPageRoute(builder: (context) => const Page1());
          default:
            return null;
        }
      },
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/page1');
          },
          child: const Text('Go to Page 1'),
        ),
      ),
    );
  }
}

class Page1 extends StatelessWidget {
  const Page1({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Page 1'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 这里可以启动子 Navigator
          },
          child: const Text('Start Sub - Navigator'),
        ),
      ),
    );
  }
}
  • 然后在 Page1 中添加子 Navigator
class Page1 extends StatelessWidget {
  const Page1({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Page 1'),
      ),
      body: Center(
        child: Navigator(
          initialRoute: '/subHome',
          onGenerateRoute: (settings) {
            switch (settings.name) {
              case '/subHome':
                return MaterialPageRoute(builder: (context) => const SubHomePage());
              case '/subPage1':
                return MaterialPageRoute(builder: (context) => const SubPage1());
              default:
                return null;
            }
          },
        ),
      ),
    );
  }
}

class SubHomePage extends StatelessWidget {
  const SubHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sub - Home Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/subPage1');
          },
          child: const Text('Go to Sub - Page 1'),
        ),
      ),
    );
  }
}

class SubPage1 extends StatelessWidget {
  const SubPage1({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sub - Page 1'),
      ),
      body: const Center(
        child: Text('This is Sub - Page 1'),
      ),
    );
  }
}

管理和处理不同层级 Navigator 的导航状态

  1. 在子 Navigator 中影响父 Navigator 的状态
    • 可以通过 GlobalKey<NavigatorState> 来访问不同层级的 Navigator
    • 首先在主 Navigator 中定义一个 GlobalKey
class MainNavigator extends StatefulWidget {
  static final GlobalKey<NavigatorState> mainNavigatorKey = GlobalKey<NavigatorState>();
  @override
  State<MainNavigator> createState() => _MainNavigatorState();
}
  • 在子 Navigator 中,如果要影响父 Navigator 的状态,例如返回上一页:
class SubPage1 extends StatelessWidget {
  const SubPage1({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sub - Page 1'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 返回父 Navigator 的上一页
            MainNavigator.mainNavigatorKey.currentState?.pop();
          },
          child: const Text('Pop Parent Navigator'),
        ),
      ),
    );
  }
}
  • 也可以通过传递回调函数的方式来处理。在父 Widget 中定义回调函数,然后传递给子 Widget,子 Widget 调用回调函数来影响父 Navigator 的状态。例如,在 Page1 中定义一个回调函数并传递给 SubPage1
class Page1 extends StatelessWidget {
  const Page1({super.key});

  void _popParentNavigator() {
    MainNavigator.mainNavigatorKey.currentState?.pop();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Page 1'),
      ),
      body: Center(
        child: Navigator(
          initialRoute: '/subHome',
          onGenerateRoute: (settings) {
            switch (settings.name) {
              case '/subHome':
                return MaterialPageRoute(builder: (context) => const SubHomePage());
              case '/subPage1':
                return MaterialPageRoute(builder: (context) => SubPage1(popParent: _popParentNavigator));
              default:
                return null;
            }
          },
        ),
      ),
    );
  }
}

class SubPage1 extends StatelessWidget {
  final VoidCallback popParent;
  const SubPage1({super.key, required this.popParent});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sub - Page 1'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: popParent,
          child: const Text('Pop Parent Navigator'),
        ),
      ),
    );
  }
}

通过上述方法,可以在 Flutter 中正确实现嵌套导航,并有效地管理和处理不同层级 Navigator 的导航状态。