Firebase实时数据库单个子节点空指针异常问题咨询
你遇到的空指针异常,核心原因是当前的dataSnapshot并不是单个评论的节点快照,而是所有评论节点的父快照,直接调用child("date")当然找不到对应的字段。
咱们看你调试时的快照数据:
DataSnapshot { key = c953b8fa-b569-4bc0-9302-3a9b34b22853, value = {0c2fd3e6-e9f1-43ce-a807-06b59e1b00bc={text=this comment is a comment., date=1515593659961, creatorId=gkbZMv2ThMh1xDwKyDP9oUtUIKi2, id=0c2fd3e6-e9f1-43ce-a807-06b59e1b00bc}} }
这里的dataSnapshot对应的是comments/{eventId}节点,它的直接子节点是那个UUID为0c2fd3e6-e9f1-43ce-a807-06b59e1b00bc的评论节点,而date是这个子节点的属性,不是当前dataSnapshot的直接属性。这就是为什么dataSnapshot.child("date").exists()返回false——它根本不在这个层级上。
解决方案
根据你的需求,有两种处理方式:
1. 遍历所有评论节点(适合获取多个评论的场景)
因为你的查询db.getReference("comments/" + eventId).orderByKey()返回的是comments/{eventId}下的所有评论节点,所以需要遍历dataSnapshot的子节点来获取每个评论的快照:
Query query = db.getReference("comments/" + eventId).orderByKey(); query.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // 遍历所有评论子节点 for (DataSnapshot commentSnapshot : dataSnapshot.getChildren()) { // 现在commentSnapshot才是单个评论的快照,能正确获取date Long date = commentSnapshot.child("date").getValue(Long.class); String text = commentSnapshot.child("text").getValue(String.class); // 处理你的业务逻辑 } } @Override public void onCancelled(DatabaseError databaseError) { // 别忘了处理取消事件 Log.e("Firebase", "查询失败", databaseError.toException()); } });
2. 直接获取单个评论节点(适合已知评论ID的场景)
如果你已经知道要获取的评论ID,直接指向该评论的节点即可,不需要用Query:
String commentId = "0c2fd3e6-e9f1-43ce-a807-06b59e1b00bc"; // 你的评论ID DatabaseReference commentRef = db.getReference("comments/" + eventId + "/" + commentId); commentRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // 这里的dataSnapshot就是单个评论的快照,可以直接取date Long date = dataSnapshot.child("date").getValue(Long.class); // ... } @Override public void onCancelled(DatabaseError databaseError) { Log.e("Firebase", "查询失败", databaseError.toException()); } });
补充说明
你提到其他String类型的字段(如text)能正常访问,大概率是之前的代码误打误撞遍历了子节点,或者你混淆了快照的层级。现在明确层级后,问题就迎刃而解了。
内容的提问来源于stack exchange,提问作者zeropointo

