使用GoRouter时无法实现App退出前的确认弹窗问题
解决GoRouter下HomePage返回键无确认弹窗问题
问题根源
GoRouter接管了Flutter的导航事件流,普通WillPopScope(已废弃)无法拦截根页面的系统返回操作,这是你之前尝试无效的核心原因。推荐使用Flutter 3.12+推出的PopScope组件,或通过GoRouter自身的导航钩子来实现需求。
方案一:使用PopScope(推荐)
直接在HomePage中用PopScope包裹整个Scaffold,拦截返回事件并弹出确认框:
import 'package:flutter/services.dart'; @override Widget build(BuildContext context) { return PopScope( // 阻止默认返回行为,交由自定义逻辑处理 canPop: false, onPopInvoked: (bool didPop) async { if (didPop) return; final shouldExit = await showDialog<bool>( context: context, builder: (context) => AlertDialog( title: const Text('确认退出'), content: const Text('确定要退出应用吗?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('取消'), ), TextButton( onPressed: () { Navigator.of(context).pop(true); // 调用系统API退出应用 SystemNavigator.pop(); }, child: const Text('确定'), ), ], ), ); }, child: Scaffold( key: HomePage.scaffoldKey, drawer: DrawerWithDropdown(), backgroundColor: tdWhite, body: const SafeArea( // 你的页面内容 ), ), ); }
方案二:通过GoRouter全局拦截
如果你需要全局统一处理返回逻辑,可以自定义GoRouter的onPopPage方法:
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); final router = GoRouter( navigatorKey: navigatorKey, routes: [ GoRoute( path: '/', builder: (context, state) => const HomePage(), ), // 其他路由配置 ], onPopPage: (route, result) async { // 判断是否为根页面的返回操作 if (route.settings.name == '/' && result == null) { final shouldExit = await showDialog<bool>( context: navigatorKey.currentContext!, builder: (context) => AlertDialog( title: const Text('确认退出'), content: const Text('确定要退出应用吗?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('确定'), ), ], ), ); if (shouldExit == true) { SystemNavigator.pop(); return false; // 阻止路由栈pop,直接退出应用 } else { return false; // 取消退出,拦截返回动作 } } return route.didPop(result); }, );
关键注意点
- 避免将拦截组件嵌套在Scaffold的
body内,需包裹整个页面组件 - 退出应用必须调用
SystemNavigator.pop(),而非仅通过Navigator操作路由栈 - 若使用旧版Flutter(<3.12),可替换为
WillPopScope并包裹Scaffold,但优先推荐PopScope
内容的提问来源于stack exchange,提问作者walid
相关产品推荐
相关产品推荐

