Flutter如何实现一键清栈不登出 解决首页按返回键跳转登录问题
问题解决步骤
1. 修复登录状态判断不生效问题
你当前的核心错误是嵌套了两层MaterialApp,Flutter全局仅需一个MaterialApp实例,多层嵌套会导致路由栈、全局上下文完全混乱,直接删掉main.dart中多余的MaterialApp即可,调整后代码如下:
修正main.dart的build方法
return StreamProvider<User?>.value( value: logic.listenToUserAuth(), initialData: null, //user signed out child: MainWrapper(routes: this.routes,), );
修正MainWrapper代码
另外你初始路由名写错了,/home_page.dart带.dart后缀和你实际配置的路由名不匹配,同时要处理Firebase auth流初始化的延迟问题,避免第一次拿到初始值null误判为未登录:
final user = Provider.of<User?>(context); // 处理初始化加载状态 if (user == null && ModalRoute.of(context)?.isCurrent != true) { return const Scaffold(body: Center(child: CircularProgressIndicator())); } // 路由名要和你routes中配置的home页路径完全一致,不要带.dart后缀 String initRout = user == null ? "/login" : "/home"; return MaterialApp( initialRoute: initRout, routes: routes, );
2. 阻止home_page按返回跳转登录页
登录成功跳转home页时,不要用Navigator.push,直接把登录页从路由栈中清除,让home页成为路由栈的根页面,按返回就不会回到登录页:
// 登录成功后的跳转逻辑,清空所有历史路由栈 Navigator.of(context).pushNamedAndRemoveUntil('/home', (route) => false);
3. 实现点返回键弹提示退出App
不要用exit(0),这个是强制杀进程,会清空内存中的Firebase登录态缓存,导致用户被登出,改用系统级退出方法SystemNavigator.pop()即可保留登录缓存。
给home_page根组件包裹返回拦截组件即可实现需求:
Flutter 3.16及以上版本用PopScope
import 'package:flutter/services.dart'; @override Widget build(BuildContext context) { return PopScope( canPop: false, onPopInvoked: (didPop) async { if (didPop) return; // 弹出确认提示 bool? exitConfirm = await showDialog( 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), child: const Text("确定"), ), ], ) ); if (exitConfirm == true) { SystemNavigator.pop(); // 系统退出,不清除登录缓存 } }, child: // 你原有home_page的页面代码 ); }
Flutter 3.16以下版本用WillPopScope
import 'package:flutter/services.dart'; @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { bool? exitConfirm = await showDialog( 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), child: const Text("确定"), ), ], ) ); return exitConfirm ?? false; }, child: // 你原有home_page的页面代码 ); }
内容的提问来源于stack exchange,提问作者user16787158
相关产品推荐
相关产品推荐

