You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用Query和ChildEventListener无法读取Firebase实时数据库数据

问题根因

你当前的代码问题出在多余的子节点遍历逻辑:
你构造的Query是查询HostID节点下所有Reference/ID等于用户输入值的子节点,onChildAdded返回的dataSnapshot本身就已经是匹配到的HostID下的完整业务节点(对应你数据库结构里HostID下的uid/pushkey级节点,包含Reference、HostLocation、TrackingID所有子字段)。
你额外遍历dataSnapshot.getChildren()后,拿到的是Reference、HostLocation、TrackingID这些单个子节点,在这些子节点中读取HostLocation、TrackingID等字段自然会失败,导致取不到TrackingID下的对应数据。

你的数据库结构参考:
数据库结构图

修复代码

直接去掉onChildAdded中的for循环即可,修改后的完整逻辑如下:

private void isTrackingID() {
    String userTrackingID = enterTracking.getText().toString().trim();
    Toast.makeText(this, "Tracking ID = " + userTrackingID, Toast.LENGTH_SHORT).show();
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("HostID");
    Query query = reference.orderByChild("Reference/ID").equalTo(userTrackingID);

    query.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String previousChildName) {
            if (dataSnapshot.exists()) {
                Log.i("checking", "this is value message");
                enterTracking.setError(null);

                // 直接从当前dataSnapshot读取字段,无需遍历子节点
                latitudefromDatabase = String.valueOf(dataSnapshot.child("HostLocation").child("latitude").getValue());
                Log.i("testing for latitude", latitudefromDatabase);
                longitudefromDatabase = String.valueOf(dataSnapshot.child("HostLocation").child("longitude").getValue());
                Log.i("testing for longitude", longitudefromDatabase);
                String hostUID = String.valueOf(dataSnapshot.child("Reference").child("uid").getValue());
                String customerAddress = String.valueOf(dataSnapshot.child("TrackingID").child(userTrackingID).child("customerAddress").getValue());
                String customerReplyStatus = String.valueOf(dataSnapshot.child("TrackingID").child(userTrackingID).child("customerReplyStatus").getValue());
                String id = String.valueOf(dataSnapshot.child("TrackingID").child(userTrackingID).child("id").getValue());
                String latitude = String.valueOf(dataSnapshot.child("TrackingID").child(userTrackingID).child("latitude").getValue());
                String longitude = String.valueOf(dataSnapshot.child("TrackingID").child(userTrackingID).child("longitude").getValue());
                String status = String.valueOf(dataSnapshot.child("TrackingID").child(userTrackingID).child("status").getValue());

                Intent intent = new Intent(getApplicationContext(), MapsActivity.class);
                intent.putExtra("hostUID", hostUID);
                intent.putExtra("hostlatitude", latitudefromDatabase);
                intent.putExtra("hostlongitude", longitudefromDatabase);
                intent.putExtra("customerAddress",customerAddress);
                intent.putExtra("customerReplyStatus",customerReplyStatus);
                intent.putExtra("id",id);
                intent.putExtra("latitude",latitude);
                intent.putExtra("longitude",longitude);
                intent.putExtra("status",status);
                // 避免重复跳转可添加FLAG_ACTIVITY_SINGLE_TOP标记
                intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
                startActivity(intent);
            } else {
                enterTracking.setError("Invalid Tracking ID from database");
                enterTracking.requestFocus();
            }
        }

        @Override
        public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
            // 数据库数据更新时触发,复用onChildAdded的读取逻辑即可
            // 如果不需要每次更新都跳转页面,建议把监听移到MapsActivity内部
            if (snapshot.exists()) {
                // 此处可编写数据更新后的处理逻辑,比如发送本地广播通知MapsActivity更新UI
            }
        }

        @Override
        public void onChildRemoved(@NonNull DataSnapshot snapshot) {
            // 对应节点被删除时的处理逻辑
        }

        @Override
        public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
            // 节点排序变更时的处理逻辑,当前场景不需要可留空
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            // 补充错误日志,方便排查权限、数据库规则问题
            Log.e("firebase_query", "查询失败: " + error.getMessage());
        }
    });
}

优化建议(解决地图页面重复刷新问题)

你之前用ValueEventListener出现的页面刷新问题,本质是每次拿到全量数据都重新启动Activity导致的,和用哪种监听器无关。更合理的实现方式是:

  1. 跳转时只把需要监听的节点key(即dataSnapshot.getKey())传给MapsActivity
  2. 在MapsActivity内部给对应节点加ChildEventListener/ValueEventListener,拿到更新数据后直接修改地图标记、更新UI,不需要重新跳转页面,性能更好也不会出现整体刷新的问题。

内容的提问来源于stack exchange,提问作者EXCITED AID

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 07:36:04