Flutter集成Firebase实时数据库问题:获取firstname值为空
解决Flutter Firebase实时数据库查询返回Null的问题
看起来你遇到的问题主要来自两个方面:Firebase查询API的使用错误,以及对查询返回的DataSnapshot结构理解有误。我来一步步帮你修正:
1. 先修正Firebase查询的API方法名
你代码里的childOrderBy和equals是错误的——Firebase实时数据库的正确方法名是orderByChild和equalTo,这会导致你的查询根本没按预期执行,可能返回不符合条件的数据或者空结果。
2. 理解查询返回的DataSnapshot结构
当你使用orderByChild+equalTo进行查询时,返回的DataSnapshot包含的是所有匹配条件的节点,而非单个节点。它的value是一个Map<String, dynamic>:其中每个键是用户节点的唯一key,对应的值才是单个用户的具体数据。
你之前直接把整个snapshot.value传给User.fromSnapShot,相当于把一个包含多个用户的集合当成了单个用户的数据,自然找不到Firstname字段,所以返回null。
3. 修正User类的构造函数
你的User类里有几个明显的低级错误,这也是导致null的原因之一:
- 构造函数误写成了
Todo.fromJson,应该是User.fromJson - 变量名
firstName和firstname大小写不一致,导致赋值失败
修正后的User类:
class User { final String key; String firstName; User.fromJson(this.key, Map<String, dynamic> data) { firstName = data['Firstname'] ?? ''; // 用空值合并运算符简化空值判断 } }
4. 重构获取用户的方法
这里分两种场景处理:如果你的查询预期返回单个用户,就取匹配结果的第一个;如果可能返回多个,就返回用户列表。
场景1:获取第一个匹配的用户
static Future<User?> getUser(String userKey) async { String accountKey = await Preferences.getAccountKey(); DataSnapshot snapshot = await FirebaseDatabase.instance .reference() .child("accounts") .child(accountKey) .child("users") .orderByChild("Group_id") .equalTo("54") .once(); // 遍历查询结果的Map,取第一个用户数据 if (snapshot.value != null) { Map<String, dynamic> usersMap = snapshot.value as Map<String, dynamic>; final firstEntry = usersMap.entries.first; return User.fromJson(firstEntry.key, firstEntry.value); } return null; // 无匹配用户时返回null }
场景2:获取所有匹配的用户
static Future<List<User>> getUsers() async { String accountKey = await Preferences.getAccountKey(); DataSnapshot snapshot = await FirebaseDatabase.instance .reference() .child("accounts") .child(accountKey) .child("users") .orderByChild("Group_id") .equalTo("54") .once(); List<User> users = []; if (snapshot.value != null) { Map<String, dynamic> usersMap = snapshot.value as Map<String, dynamic>; usersMap.forEach((userKey, userData) { users.add(User.fromJson(userKey, userData)); }); } return users; }
额外提示:简化异步代码
你之前用Completer的方式可以直接用async/await替代,代码会更简洁易读,上面的示例已经采用了这种写法。
现在再测试一下,应该就能正确获取到firstName的值了!
内容的提问来源于stack exchange,提问作者Jérôme Bonjour
相关产品推荐
相关产品推荐

