结合GetX与Firebase Auth的Firestore查询登出后权限报错问题
问题解决
根因说明
HomeBinding中给UserController配置了fenix: true,该参数作用是Controller被销毁后保留实例缓存,下次获取时直接复用旧实例。而onInit生命周期仅在实例首次创建时执行一次,重新登录后复用旧实例不会重新触发Firestore流绑定逻辑,所以刷新失败。- 登出时仅执行了路由跳转操作,没有主动销毁
UserController,也没有取消已绑定的Firestore流订阅。登出后账号处于未登录状态,Firestore安全规则校验不通过,仍在活跃的流就会抛出权限错误。
修复步骤
1. 改造UserController,主动管理流订阅
在Controller销毁时手动取消所有流订阅,释放资源:
class UserController extends GetxController { final UserRepository _userRepository = UserRepository(); final repository = UserRepository(); final users = Rx<List<FirestoreUser>>([]); late Rx<FirestoreUser> _firestoreUser; FirestoreUser get firestoreUser => _firestoreUser.value; // 保存流订阅对象 StreamSubscription? _currentUserSub; StreamSubscription? _allUsersSub; @override void onInit() { super.onInit(); final user = FirebaseAuth.instance.currentUser; if (user == null) return; _firestoreUser = Rx<FirestoreUser>(FirestoreUser.fromAuth(user)); // 保存订阅返回值 _currentUserSub = _firestoreUser.bindStream(_userRepository.getUserById(user.uid)); getAllUsers(); } void getAllUsers() { _allUsersSub = users.bindStream(repository.getAllUsers()); } @override void onClose() { // 销毁前取消所有订阅 _currentUserSub?.cancel(); _allUsersSub?.cancel(); users.close(); _firestoreUser.close(); super.onClose(); } }
2. 登出时主动销毁UserController
修改AuthController的登录状态处理逻辑,登出时强制删除UserController实例,彻底清理残留资源:
handleAuthChanged(User? user) { print("handleAuthChanged - ${user?.uid}"); if (user == null) { // 登出前销毁UserController Get.delete<UserController>(); Get.offAll(() => LoginScreen()); } else { Get.offAll(() => HomeScreen(), binding: HomeBinding()); } }
3. 移除不必要的fenix配置
如果没有特殊的实例复用需求,删除HomeBinding中的fenix: true,避免旧实例被意外复用:
class HomeBinding extends Bindings { @override void dependencies() { Get.lazyPut<UserController>(() => UserController()); } }
内容的提问来源于stack exchange,提问作者Nelson.b.austin
相关产品推荐
相关产品推荐

