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

Flutter Provider接收空数据 如何动态传登录用户信息到Bloc

问题解决方案

核心原因是应用启动阶段还未完成登录认证流程,无法获取有效用户信息,此时在main函数中初始化IncidentBloc传入空的UserModel自然会出现空值问题,不要在应用根节点初始化时强依赖登录态,按以下步骤调整即可实现动态获取当前登录用户数据:

第一步:改造Bloc逻辑,自动监听登录状态

不要在Bloc构造函数中固定传入单次UserModel,改为在Bloc内部监听登录状态变化,登录成功后自动加载对应用户数据,同时修复原有代码中readData方法未传入id参数的问题:

class IncidentBloc implements BlocBase {
  IncidentBloc() {
    // 监听Firebase Auth全局登录状态,登录/退出自动触发
    FirebaseAuth.instance.authStateChanges().listen((firebaseUser) {
      if (firebaseUser != null) {
        // 转换为项目自定义的UserModel
        currentUser = UserModel(email: firebaseUser.email!);
        // 取消旧订阅防止内存泄漏
        _dataSubscription?.cancel();
        // 订阅当前登录用户的Firestore数据
        _dataSubscription = db.init(currentUser!).listen((data) => _inFirestore.add(data));
      } else {
        // 未登录状态清空缓存数据
        currentUser = null;
        _inFirestore.addError('用户未登录');
      }
    });
  }

  UserModel? currentUser;
  StreamSubscription<QuerySnapshot>? _dataSubscription;

  final _idController = BehaviorSubject<String>();
  Stream<String> get outId => _idController.stream;
  Sink<String> get _inId => _idController.sink;

  final _firestoreController = BehaviorSubject<QuerySnapshot>();
  Stream<QuerySnapshot> get outFirestore => _firestoreController.stream;
  Sink<QuerySnapshot> get _inFirestore => _firestoreController.sink;

  void readData(String id) async {
    if (currentUser == null) return;
    db.readData(id, currentUser!);
  }


  @override
  void dispose() {
    _dataSubscription?.cancel();
    _firestoreController.close();
    _idController.close();
  }
}

第二步:调整main入口初始化逻辑

启动时不需要传入空的UserModel,直接初始化无参IncidentBloc即可,Bloc内部会自动感知登录状态:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  BlocOverrides.runZoned(
    () => runApp(
      BlocProviderr(bloc: IncidentBloc(), child: const App())
    ),
    blocObserver: AppBlocObserver(),
  );
}

第三步:修复DB层集合名不一致问题

原有代码中两个方法的一级集合名存在空格差异(一个是CollectionName、一个是Collection Name),会导致找不到对应数据,统一集合名称:

class DB {
  final db = FirebaseFirestore.instance;

  Stream<QuerySnapshot> init(UserModel user) {
    return db
        .collection('CollectionName')
        .doc(user.email)
        .collection('New Collection')
        .snapshots();
  }


  void readData(String id, UserModel user) async {
    DocumentSnapshot snapshot = await db
        .collection('CollectionName') // 和上方集合名保持一致
        .doc(user.email)
        .collection('New Collection')
        .doc(id)
        .get();
    print(snapshot['name']);
  }

}

DB db = DB();

如果项目使用的是自定义后端登录而非Firebase Auth,只需要把Bloc中监听FirebaseAuth.instance.authStateChanges()的逻辑替换为项目自身的登录状态流即可,登录成功后将获取到的UserModel赋值给currentUser,再触发一次Firestore数据订阅,全程不需要硬编码用户邮箱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:54:18