Firebase实时数据库如何在未知节点键的情况下获取子记录
问题原因
- 异步执行问题:Firebase的
ValueEventListener是异步回调的,你在回调外部读取tipoUserBD[0]的时候,onDataChange还没触发执行,所以拿到的是初始的null值 - 全量遍历效率低:你当前的实现是拉取整个users节点的所有数据再遍历筛选,数据量多的时候性能很差,还会浪费用户带宽
正确实现方案
优先用Firebase自带的查询能力筛选匹配邮箱的用户节点,同时把使用tipo字段的逻辑放到回调内执行:
database = FirebaseDatabase.getInstance().getReference("users"); // 直接筛选email等于目标邮箱的节点,不需要全量拉取 Query query = database.orderByChild("email").equalTo(user.getEmail()); query.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if(snapshot.exists()){ for(DataSnapshot userSnapshot : snapshot.getChildren()){ String tipo = userSnapshot.child("tipo").getValue(String.class); // 这里直接使用tipo的值,比如更新UI、做逻辑判断都在这里写 // 不要试图把tipo赋值给外部变量之后在外部读取,异步逻辑执行顺序不匹配 Log.d("tipoUsuario", "获取到的tipo值:" + tipo); } } } @Override public void onCancelled(@NonNull DatabaseError error) { // 不要空着onCancelled,至少加个日志打印排查错误 Log.e("Firebase查询错误", error.getMessage()); } });
额外注意事项
- 要给
users节点的email字段加索引,否则查询会报警告性能也差,在Firebase控制台的 Realtime Database 规则里添加如下配置:
{ "rules": { "users": { ".indexOn": "email" } } }
- 如果必须要在回调外部使用拿到的tipo值,可以自定义回调接口来处理异步结果,不要用数组这种方式中转。
内容的提问来源于stack exchange,提问作者thai.png
相关产品推荐
相关产品推荐

