从 Firebase 获取具有唯一 ID 的子项的值

Posted

技术标签:

【中文标题】从 Firebase 获取具有唯一 ID 的子项的值【英文标题】:Getting the value of a child of a unique ID from Firebase 【发布时间】:2021-12-09 13:40:50 【问题描述】:

我正在尝试从实时数据库中显示用户的当前位置,但它没有显示在地图上,数据库的结构如下:


  "Blocked Users" : 
    "RCX2HZXIwlSmMHFgDytf1DgZBgi2" : 0
  ,
  "User Location" : 
    "RCX2HZXIwlSmMHFgDytf1DgZBgi2" : 
      "latitude" : 37.4035483,
      "longitude" : -122.097715
    
  ,
  "Users" : 
    "RCX2HZXIwlSmMHFgDytf1DgZBgi2" : 
      "Alert Level" : "High",
      "Emergency Type" : "Natural Disaster",
      "address" : "Lapaz Tarlac",
      "emergencyNum" : "0981232387346",
      "name" : "Rafael Campos",
      "phoneNum" : "0981233445675"
    
  

我在使用 onMapReady 中的代码从 Firebase 获取位置时遇到 NPE,我应该如何解决这个问题?

@Override
    public void onMapReady(@NonNull GoogleMap googleMap) 
        mMap = googleMap;

        DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("Users");
        DatabaseReference uidRef = rootRef.child("User Location");

        uidRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() 
            @Override
            public void onComplete(@NonNull Task<DataSnapshot> task) 
                if (task.isSuccessful()) 
                    DataSnapshot snapshot = task.getResult();
                    Double latitude = snapshot.child("latitude").getValue(Double.class);
                    Double longitude = snapshot.child("longitude").getValue(Double.class);
                    LatLng location = new LatLng(latitude, longitude);
                    mMap.addMarker(new MarkerOptions().position(location).title(getCompleteAddress(latitude, longitude)));
                    mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location,14F));
                    Log.d("TAG", "latitude, longitude");
                 else 
                    Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
                
            
        );


    

这是堆栈跟踪:

2021-10-23 11:19:19.139 12376-12376/com.example.rescuealertadmin E/androidRuntime: FATAL EXCEPTION: main
    Process: com.example.rescuealertadmin, PID: 12376
    java.lang.NullPointerException: Attempt to invoke virtual method 'double java.lang.Double.doubleValue()' on a null object reference
        at com.example.rescuealertadmin.RetrieveMapsActivity$4.onComplete(RetrieveMapsActivity.java:202)
        at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks@@17.2.1:1)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

【问题讨论】:

嘿拉斐尔。您已接受使用 100% 复制解决方案的答案。这不是你应该处理这种情况的方式。 嘿 Rafael,我可能复制了一个解决方案,但我已经在任何人之前回答了您的评论。 【参考方案1】:

您收到以下错误:

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“double java.lang.Double.doubleValue()”

因为您在代码中使用了不正确的引用。如我所见,“纬度”和“经度”都是 UID 的直接子级。所以请更改以下代码行:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("Users");
DatabaseReference uidRef = rootRef.child("User Location");
uidRef.get().addOnCompleteListener(/* ... /*);

收件人:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("User Location").child(uid);
uidRef.get().addOnCompleteListener(/* ... /*);

其余代码可能保持不变。

【讨论】:

【参考方案2】:

您的User Location 路径有一个用户列表,因此您的onComplete 需要通过循环遍历结果来处理DataSnapshot 也有一个子节点列表的事实:

uidRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() 
    @Override
    public void onComplete(@NonNull Task<DataSnapshot> task) 
        if (task.isSuccessful()) 
            DataSnapshot snapshot = task.getResult();
            for (DataSnapshot child: snapshot.getChildren()) 
                Double latitude = child.child("latitude").getValue(Double.class);
                Double longitude = child.child("longitude").getValue(Double.class);
                LatLng location = new LatLng(latitude, longitude);
                ...
    
);

【讨论】:

它仍然没有显示用户的位置,只是整个地图。 如果错误消息消失,此更改解决了您发布的问题。您可能还有其他问题,但这绝对是其中之一 - 也是导致错误消息的问题。为了进一步排除故障,我建议在onComplete 的第一行设置断点,并单步执行代码以查看您得到的值。【参考方案3】:

您在错误的节点上查找数据。

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("Users");

这里您保存了用户信息

DatabaseReference uidRef = rootRef.child("User Location");

然后您将进一步进入“用户”节点。但是“用户”节点中没有“用户位置”。

如果你有 UID,你可以得到这样的数据

DatabaseReference uidRef = FirebaseDatabase.getInstance().getReference("User Location").child(UID);

【讨论】:

我已经修复了引用,但地图仍然没有显示用户的位置。【参考方案4】:

您提供了错误的参考路径,这就是您获得 NPE 的原因。

转换自:

DatabaseReference rootRef = 
FirebaseDatabase.getInstance().getReference("Users");
DatabaseReference uidRef = rootRef.child("User Location");
uidRef.get().addOnCompleteListener(/* ... /*);

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = 
FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("User Location").child(uid);
uidRef.get().addOnCompleteListener(//);

【讨论】:

我已经修复了引用,但地图仍然没有显示用户的位置。 你得到什么回应? 我尝试删除参考中的 '.child(uid)',标记出现,但它在 logcat 中显示'No setter/field for found on class com.example.rescuealertadmin .LocationSend(这是我的班级) 只需在 logcat 中打印整个快照以显示您得到的内容。 我终于得到了我想要的结果,我放弃了整个参考纬度和经度,只是把它放在 for 循环中:“LocationSend send = ds.getValue(LocationSend.class); "

以上是关于从 Firebase 获取具有唯一 ID 的子项的值的主要内容,如果未能解决你的问题,请参考以下文章

检查firebase子项是不是具有特定值[重复]

Firebase如何添加具有给定名称的子节点?

如何一次获取所有 firebase 数据子项?

具有 facebook 身份验证和唯一 ID 的 Firebase 规则

如何获取firebase生成的唯一ID [关闭]

如何查询 Firebase 中不存在子项的位置? [复制]