You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter authStateChanges监听报widget卸载无context异常解决方法

报错根因

FirebaseAuth.instance.authStateChanges().listen 注册的是持续生效的流订阅,当承载这段逻辑的Widget被销毁(unmounted)后,订阅不会自动取消,如果此时认证状态变化触发回调,回调内访问已经失效的context执行导航操作,就会抛出该异常。
你注释掉的mounted判断是必要修复手段,配合订阅取消逻辑,完全不会影响原有pushAndRemoveUntil跳转、触发页面dispose的业务需求。

修复方案
  • 存储流订阅实例,在Widget的dispose生命周期中主动取消订阅,从根源避免Widget销毁后回调被触发
  • 所有访问context、执行导航操作的逻辑之前,增加mounted判断,只有当前Widget处于活跃挂载状态时才执行后续逻辑
  • 修正代码中重复声明user变量的问题:监听回调已经返回最新的user对象,不需要额外调用FirebaseAuth.instance.currentUser取值,避免状态不一致
  • 不要把监听注册逻辑放在build方法内,build会随页面刷新反复执行,会生成多个重复订阅,导致逻辑重复触发、内存泄漏,监听注册逻辑应该放在initState生命周期中执行
完整修复代码

在对应State类中声明订阅变量,重写initState和dispose方法:

class _YourPageState extends State<YourPage> {
  // 声明认证状态监听的订阅实例
  late StreamSubscription<User?> _authStateSub;
  UserModel loggedInUser = UserModel();

  @override
  void initState() {
    super.initState();
    // 在initState中注册监听,避免重复创建
    _authStateSub = FirebaseAuth.instance.authStateChanges().listen((User? user) {
      // 先判断当前Widget是否还处于挂载状态,未挂载直接终止逻辑
      if (!mounted) return;

      if (user == null) {
        print('------------------------------------------------------User is currently signed out!');
        print(user);
        Navigator.pushAndRemoveUntil(
          context,
          MaterialPageRoute(builder: (BuildContext context) => const LoginScreen()),
          (Route<dynamic> route) => false
        );
      } else {
        print(user);
        print('--------------------------------------------------User is signed in!');
        Navigator.of(context).pushAndRemoveUntil(
          MaterialPageRoute(builder: (context) => const loadData()),
          (Route<dynamic> route) => false
        );
      }
    });
  }

  @override
  void dispose() {
    // 页面销毁时主动取消订阅,释放资源
    _authStateSub.cancel();
    super.dispose();
  }

  // 原有build逻辑保持不变
  @override
  Widget build(BuildContext context) {
    // ... 你的原有页面构建代码
  }
}
说明

原有pushAndRemoveUntil跳转逻辑完全保留,跳转时会清空全部历史路由栈,被移除的页面会正常触发dispose生命周期,符合业务要求。
mounted判断只会拦截Widget已经销毁后的无效导航操作,正常场景下的登录、登出跳转逻辑不会受任何影响。

内容的提问来源于stack exchange,提问作者CodeConfusion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:15:40