Flutter-Firebase RTDB疑问:读取数据必须用Push ID吗?如何避免冗余Push ID?
问题分析与解决方案
这绝对不是预期的行为,问题的核心出在你写入数据时错误使用了push()方法——这正是Firebase自动生成随机Push ID的原因,直接导致了你的数据结构偏离预期,进而引发读取失败。
为什么会出现随机Push ID?
你当前的写入代码中:
await FirebaseAuth.instance.signInWithEmailAndPassword( email: email, password: password).then((value) { if(value.user.uid != null ) { final dbRef = FirebaseDatabase.instance.reference().child('users'); dbRef.push().child(user.uid.toString()).set(User().toJson()); } }
这里的push()方法会自动在users节点下生成一个随机的唯一ID(就是你看到的MFvvXpeRmoQvXkd5VS8),然后你又在这个随机ID节点下创建了以uid为键的子节点,最终数据结构完全偏离了你的预期:
-users ------随机Push ID ----------uid -----------firstName -----------lastName
这就导致你直接通过users/uid路径读取时,自然会得到null。
如何避免生成随机Push ID?
只需要移除多余的push()调用,直接将用户的uid作为users节点的子节点键,就能得到你最初预期的数据库结构:
修正后的写入代码
await FirebaseAuth.instance.signInWithEmailAndPassword( email: email, password: password ).then((value) { if(value.user?.uid != null ) { final dbRef = FirebaseDatabase.instance.reference().child('users'); // 直接用uid作为子节点键,不再调用push() dbRef.child(value.user!.uid).set(User().toJson()); } });
修正后生成的数据库结构会完全符合你的预期:
-users ------uid -----------firstName -----------lastName
修正后的读取代码
现在你可以直接通过users/uid路径读取用户数据,不需要额外的equalTo或复杂监听:
final dbRef = FirebaseDatabase.instance.reference().child('users').child(user.uid); // 一次性读取数据 dbRef.once().then((snapshot) { if(snapshot.value != null) { User userInfo = User.fromJson(snapshot.value as Map<String, dynamic>); // 处理读取到的用户信息 } }); // 或者实时监听数据变化 dbRef.onValue.listen((event) { if(event.snapshot.value != null) { User userInfo = User.fromJson(event.snapshot.value as Map<String, dynamic>); readUserInfo(userInfo); } });
为什么硬编码Push ID能读到数据?
因为你硬编码Push ID后,访问的路径是users/随机Push ID/uid,正好匹配了错误写入后的数据结构,所以能拿到数据,但这显然不是可扩展的正确做法——总不能每次都手动记录Push ID吧?
内容的提问来源于stack exchange,提问作者Dharshan Anandappa
相关产品推荐
相关产品推荐

