Firebase中使用动态Key获取值时返回空字符串问题求助
我来帮你捋捋这个问题!你遇到的情况很典型——动态用一个字段的值作为Key去取另一个字段,但拿到空值,大概率是这几个环节出了问题,咱们一步步排查:
首先先把你的代码贴出来方便参考:
for (DataSnapshot ds : dataSnapshot.getChildren()) { kn = ds.child("keyname").getValue().toString(); position1 = ds.child("position").getValue().toString(); value=ds.child(kn).getValue().toString(); }
可能的原因及解决方法
动态Key的准确性问题
首先要确认keyname的值和数据库里实际存在的Key完全一致!Firebase的节点Key是大小写敏感的,而且不能有多余空格、特殊字符(除非你特意存储的)。比如如果数据库里的Key是userAge,但keyname的值是UserAge或者user age,那肯定找不到对应字段。
解决方法:在获取kn之后立刻打印日志,看看它的值到底是什么,再和Firebase控制台里的节点Key对比:Log.d("FirebaseCheck", "当前keyname的值是: " + kn);取值方式不安全导致的空值假象
你直接用.getValue().toString()有个隐患:如果字段不存在,.getValue()会返回null,调用null.toString()会抛出空指针异常,但你说得到的是空字符串,可能是某些情况下Firebase返回了空字符串?或者你已经捕获了异常?
更安全的做法是用.getValue(String.class),它会直接返回字符串类型的值,不存在的话返回null,避免空指针:String kn = ds.child("keyname").getValue(String.class); if (kn == null) { Log.d("FirebaseCheck", "这个节点里没有keyname字段"); continue; // 跳过这个节点 }动态Key不在当前DataSnapshot的层级下
仔细检查你的数据库结构!比如你是不是误以为kn对应的字段是当前ds的直接子节点,但实际上它在更深的层级?比如数据库结构是这样:parentNode - childNode1 - keyname: "detail" - position: "1" - detail - value: "xxx" // 这里的detail是嵌套的,不是直接子节点那你用
ds.child(kn)就取不到,得改成ds.child(kn).child("value")或者对应路径。提前判断字段是否存在
在取值前先调用ds.hasChild(kn)判断该Key是否存在,这样能明确知道是字段不存在还是其他问题:if (ds.hasChild(kn)) { String value = ds.child(kn).getValue(String.class); Log.d("FirebaseCheck", "拿到的值: " + value); } else { Log.d("FirebaseCheck", "当前节点没有名为" + kn + "的子节点"); }
修改后的完整示例代码
把这些优化点整合起来,代码会更健壮,也方便调试:
for (DataSnapshot ds : dataSnapshot.getChildren()) { // 安全获取keyname String kn = ds.child("keyname").getValue(String.class); if (kn == null) { Log.d("FirebaseDebug", "跳过:keyname不存在"); continue; } Log.d("FirebaseDebug", "当前keyname值: " + kn); // 安全获取position String position1 = ds.child("position").getValue(String.class); // 判断并获取目标值 if (ds.hasChild(kn)) { String value = ds.child(kn).getValue(String.class); Log.d("FirebaseDebug", "成功获取值: " + value); } else { Log.d("FirebaseDebug", "未找到key为" + kn + "的字段"); } }
按照这个思路一步步排查,应该能很快找到问题所在!
内容的提问来源于stack exchange,提问作者Faisal Nazir

