从Firebase读取数据存入Flutter Map时返回null的问题
问题原因与解决办法
问题根源
你使用的snapshots()返回的是StreamforEach是异步执行的——只有当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
相关产品推荐
相关产品推荐

