登录后再次登录,注销功能失效需重启应用问题求助
Flutter跨平台应用注销失效问题排查与修复
问题现象
开发Android/iOS跨平台应用时,首次登录后注销功能正常,但再次登录后,注销功能完全失效,必须重启应用才能恢复正常。
现有注销代码
注销按钮点击事件
ListTile( leading: Icon( Iconsax.logout, color: Colors.red, ), title: Text( 'logout'.tr, style: TextStyle(color: Colors.red), ), onTap: () { Geofire.removeLocation(currentFirebaseUser!.uid); rideRequestRef!.onDisconnect(); rideRequestRef!.remove(); rideRequestRef = null; loggOut(context); }, )
核心注销方法
void loggOut(BuildContext context) { showDialog( context: context, barrierDismissible: true, builder: (BuildContext context) { return ProgressDialog(message: 'logging_out'.tr); }); FirebaseAuth.instance.signOut(); GoogleSignIn().signOut(); Future.delayed(Duration(seconds: 2), () { Navigator.pushNamedAndRemoveUntil( context, BeforeLogin.idScreen, (route) => false); displayToast('loggedout_success'.tr, context); }); }
问题根源分析
- Firebase引用未正确重置/更新:再次登录后,
currentFirebaseUser和rideRequestRef可能未重新赋值,导致注销时空断言(!)抛出异常,后续操作中断。 - GoogleSignIn实例未复用:每次注销都创建新的
GoogleSignIn()实例,无法匹配当前登录会话,导致signOut操作无效。 - onDisconnect操作错误:
rideRequestRef!.onDisconnect()仅注册断开监听,未绑定具体移除动作,无法确保断开时清理数据。 - 异步操作未同步:未等待Firebase、Google登录的注销操作完成就执行导航,导致状态未同步,UI残留旧状态。
修复方案
1. 复用GoogleSignIn实例
在全局或状态类中初始化实例,避免每次注销创建新对象:
// 类顶部或全局定义 final GoogleSignIn _googleSignIn = GoogleSignIn(); // 注销方法中使用复用的实例 void loggOut(BuildContext context) { // ... 其他代码 FirebaseAuth.instance.signOut(); _googleSignIn.signOut(); // ... 其他代码 }
2. 完善Firebase引用清理逻辑
添加空值判断,避免空断言异常,同时修正onDisconnect操作:
onTap: () async { if (currentFirebaseUser != null) { await Geofire.removeLocation(currentFirebaseUser!.uid); } if (rideRequestRef != null) { await rideRequestRef!.onDisconnect().remove(); await rideRequestRef!.remove(); rideRequestRef = null; } loggOut(context); },
3. 等待异步操作完成后再导航
取消固定延迟,等待所有注销操作完成后执行导航:
void loggOut(BuildContext context) async { showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return ProgressDialog(message: 'logging_out'.tr); }); await FirebaseAuth.instance.signOut(); await _googleSignIn.signOut(); Navigator.pop(context); Navigator.pushNamedAndRemoveUntil( context, BeforeLogin.idScreen, (route) => false); displayToast('loggedout_success'.tr, context); }
4. 登录时重置全局状态
登录成功后重新初始化用户和请求引用,避免使用旧数据:
void onLoginSuccess(User user) { currentFirebaseUser = user; rideRequestRef = FirebaseDatabase.instance.ref().child('rideRequests').child(user.uid); // 其他初始化逻辑 }
额外建议
- 避免使用空断言(
!),改用空安全的条件判断(?.或if != null),防止运行时异常中断功能。 - 借助状态管理工具(如Provider、Bloc)管理用户登录状态,确保注销/登录时状态同步。
内容的提问来源于stack exchange,提问作者Ankit Kumar Singh
相关产品推荐
相关产品推荐

