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

使用Firebase实现登录逻辑时触发Bad state异常问题

解决Firebase Realtime Database的"Bad state: Cannot fire new event. Controller is already firing an event"错误

问题描述

执行用户创建操作时,调用ref.child('users/$id').set(...)触发以下异常,但用户数据仍能成功写入Firebase:

Exception has occurred.
DartError: Bad state: Cannot fire new event. Controller is already firing an event

堆栈追踪指向database_reference_web.dart第51行的set方法,仅发生在用户不存在的正向创建场景中。

可能原因

该错误源于Firebase Web SDK的事件控制器在异步操作中的状态冲突,常见诱因:

  • 复用同一个DatabaseReference实例执行多次异步操作,导致内部事件流冲突
  • 使用的Firebase SDK版本存在异步处理的已知bug

解决方案

方案1:每次操作创建新的DatabaseReference实例

避免复用类成员变量的ref,在每个方法内创建独立的引用实例:

class DatabaseOperations {
  static final FirebaseDatabase database = FirebaseDatabase.instance;

  Future<UserModel?> getUserByEmail(String username) async {
    final ref = FirebaseDatabase.instance.ref();
    var response = await ref
        .child('users')
        .orderByChild('username')
        .equalTo(username)
        .once();

    if (!response.snapshot.exists) {
      return null;
    }

    var userMap = Map<String, dynamic>.from(response.snapshot.value as Map);
    var user = UserModel.fromJson(userMap);

    return user;
  }

  Future<UserModel?> getUserById(String id) async {
    final ref = FirebaseDatabase.instance.ref();
    var response =
        await ref.child('users').orderByChild('id').equalTo(id).once();

    if (!response.snapshot.exists) {
      return null;
    }

    var user =
        UserModel.fromJson(response.snapshot.value as Map<String, dynamic>);

    return user;
  }

  Future<bool> addUser(UserModel user, BuildContext context) async {
    final ref = FirebaseDatabase.instance.ref();
    if (await getUserByEmail(user.username!) != null)
    {
      if (context.mounted) {
        await showDialog(
            context: context,
            builder: (BuildContext context) {
              return AlertDialog(
                title: const Text('Error'),
                content: const Text('User already exists'),
                actions: <Widget>[
                  TextButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    child: const Text('OK'),
                  ),
                ],
              );
            });
      }

      return false;
    }

    var id = Uuid().v4();

    await ref.child('users/$id').set({'username': user.username, 'password': user.password});

    return await getUserById(id) != null;
  }
}

方案2:升级Firebase相关依赖版本

检查pubspec.yaml中的Firebase依赖,升级到最新稳定版(旧版本的异步处理bug已被修复):

dependencies:
  firebase_core: ^2.15.0
  firebase_database: ^10.2.0

执行flutter pub upgrade完成依赖更新。

方案3:用runZonedGuarded捕获异常(临时规避)

如果暂时无法修改引用逻辑或升级SDK,可使用runZonedGuarded包裹set操作,避免异常阻断业务流程:

await runZonedGuarded(() async {
  await ref.child('users/$id').set({'username': user.username, 'password': user.password});
}, (error, stackTrace) {
  // 可在此记录错误日志,不影响后续流程
  print('Set operation error: $error');
});

额外优化建议

  • 禁止明文存储密码:使用哈希算法(如SHA-256)对密码加密后再存入数据库
  • 优先使用Firebase Authentication替代自定义登录逻辑,更安全且无需手动处理用户存在性校验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:34:54