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

从Firebase读取数据存入Flutter Map时返回null的问题

问题原因与解决办法

问题根源

你使用的snapshots()返回的是Stream,它的forEach是异步执行的——只有当Firebase返回数据后,这个回调才会触发。但你在forEach外的print(userProfile["phone"])是同步代码,会先于异步回调执行,此时userProfile还没被赋值,自然返回null。

另外,你初始化userProfile为空Map,即便没有报错,在异步回调触发前,取phone键也会得到null。


解决方案

方案1:仅获取一次数据(无需实时监听)

用get()替代snapshots(),配合async/await等待数据返回:

Future<void> buildUserSettingField() async {
  Map<String, dynamic>? userProfile = {};

  try {
    final doc = await FirebaseFirestore.instance
        .collection("subscribers")
        .doc("905531235544")
        .get();
    userProfile = {
      "name": doc["name"],
      "phone": doc["phone"],
      "email": doc["email"],
      "password": doc["password"],
      "date": doc["date"]
    };
    print(userProfile["phone"]);
  } catch (e) {
    debugPrint("settingERROR: $e");
  }
}

方案2:需要实时监听数据变化(基于Stream)

用await for或listen确保在数据返回后再操作:

方式A:await for 遍历Stream
Future<void> buildUserSettingField() async {
  Map<String, dynamic>? userProfile = {};

  final users = FirebaseFirestore.instance
      .collection("subscribers")
      .doc("905531235544")
      .snapshots();
  
  await for (final element in users) {
    try {
      userProfile = {
        "name": element["name"],
        "phone": element["phone"],
        "email": element["email"],
        "password": element["password"],
        "date": element["date"]
      };
      print(userProfile["phone"]); // 数据返回后才会执行这里
    } catch (e) {
      debugPrint("settingERROR: $e");
    }
  }
}
方式B:listen 监听数据更新
void buildUserSettingField() {
  Map<String, dynamic>? userProfile = {};
  StreamSubscription? subscription; // 保存订阅对象,用于后续取消

  final users = FirebaseFirestore.instance
      .collection("subscribers")
      .doc("905531235544")
      .snapshots();
  
  subscription = users.listen((element) {
    try {
      userProfile = {
        "name": element["name"],
        "phone": element["phone"],
        "email": element["email"],
        "password": element["password"],
        "date": element["date"]
      };
      print(userProfile["phone"]); // 每次数据更新都会触发
    } catch (e) {
      debugPrint("settingERROR: $e");
    }
  });

  // 在组件销毁时取消订阅,避免内存泄漏
  // 比如在StatefulWidget的dispose方法中调用:subscription?.cancel();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:25:29