Flutter Web接入Firebase Auth后刷新断认证、登录无限加载问题求助
问题成因
- Firebase JS SDK版本不兼容:index.html中引入的Firebase JS SDK版本不一致,firestore使用7.22.1,其余组件使用8.6.1,跨大版本混用会导致认证、数据库模块的交互异常,直接影响认证状态的读取和持久化。另外代码中存在未定义变量的错误:
firebase.getAnalytics(app)中的app变量未声明,也没有引入Firebase Analytics的SDK,初始化阶段的JS报错会阻塞后续认证逻辑的执行。 - Auth状态监听逻辑缺陷:
watchAuthChange方法被放在build函数中调用,每次页面重绘都会新增一个重复的authStateChanges监听,导致内存泄漏、状态更新逻辑被多次触发,出现状态覆盖异常。- 监听回调的判断逻辑存在漏洞:首次触发监听时如果firebaseUser为null(Firebase Auth异步初始化的中间状态),仅修改状态直接返回,不会同步更新
_firebaseUser变量,后续如果拿到已登录的用户信息时,部分场景下会出现判断异常,导致状态卡在progress不更新,出现无限加载。
- 认证持久化未显式配置:你使用的0.18.0版本firebase_auth插件,Flutter Web端默认的认证持久化策略可能存在异常,刷新页面后本地存储的认证凭据没有被正常读取,导致认证状态丢失。
- 重复的用户模型订阅:
_initUserModel方法中注释了订阅存在性判断,每次认证状态更新为signin时都会新增一个用户数据流监听,多次触发会导致资源占用过高,甚至出现逻辑异常。
解决方案
- 修复index.html的SDK配置
统一所有Firebase JS SDK的版本,删除无效的Analytics代码,修改后参考如下:
<script src = "https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-firestore.js"></script> <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-storage.js"></script> <script> var firebaseConfig = { // 补充你自己的配置项 apiKey: "xxx", authDomain: "xxx", projectId: "xxx", storageBucket: "xxx", messagingSenderId: "xxx", appId: "xxx" }; firebase.initializeApp(firebaseConfig); </script>
- 重构Auth状态监听逻辑
将watchAuthChange的调用从build方法中移除,改为在FirebaseAuthState的构造函数中仅调用一次,同时简化监听回调的逻辑,每次收到状态变更都直接更新:
class FirebaseAuthState extends ChangeNotifier { FirebaseAuthStatus _firebaseAuthStatus = FirebaseAuthStatus.progress; final FirebaseAuth _firebaseAuth = FirebaseAuth.instance; User? _firebaseUser; StreamSubscription? _authSub; FirebaseAuthState() { // 显式开启本地持久化,确保刷新后认证状态保留 _firebaseAuth.setPersistence(Persistence.LOCAL); watchAuthChange(); } void watchAuthChange() { _authSub?.cancel(); _authSub = _firebaseAuth.authStateChanges().listen((firebaseUser) { _firebaseUser = firebaseUser; changeFirebaseAuthStatus(); }); } // 其余原有代码保持不变 @override void dispose() { _authSub?.cancel(); super.dispose(); } }
- 修复用户模型重复订阅问题
恢复_initUserModel中的订阅存在性判断,避免重复创建监听:
_initUserModel(FirebaseAuthState firebaseAuthState, BuildContext context) { UserModelState userModelState = Provider.of<UserModelState>(context, listen: false); // 已有订阅直接返回 if (userModelState.currentStreamSub != null) return; userModelState.currentStreamSub = userNetworkRepo .getUserModelStream(firebaseAuthState.firebaseUser.uid) .listen((userModel) { userModelState.userModel = userModel; }); }
- 可选优化
如果项目允许,建议将firebase相关依赖升级到最新的空安全版本,旧版本(0.5.x系列)的Flutter Web Firebase插件存在较多已知的兼容性问题,升级后可以避免很多底层异常。
内容的提问来源于stack exchange,提问作者Kevin Yang
相关产品推荐
相关产品推荐

