android 的多个(嵌套)ValueEventListeners 在 firebase 实时数据库中不工作

multiple(nested) ValueEventListeners not working in firebase realtime database for android

我正在处理的项目在 firebase 实时数据库中有 3 个 "tables",即:

用户(包含用户的登录信息,例如电子邮件、密码、手机号码等)

VictimProfiles(包含基本个人资料信息,如个人资料图片字符串、姓名、职位和来自用户的相应用户 ID table)

VolunteerProfiles(包含Address、latitude、longitude、availability timing以及对应的UserID和VictimProfileID(Firebase生成的))

在我的 Google 地图 activity 中,我需要在每个志愿者以及当前使用该应用程序的用户的位置上放置标记,并提供自定义信息 window 显示有关志愿者的必要信息, 然而,如下面的代码所示,当我尝试从志愿者 table 的 ValueEventListener 中访问 VictimProfile 和 Users table 时,他们的数据没有写入 public 字符串我正在写信给。我知道这听起来很复杂,但看看代码,您就会明白我的意思

    public void DropVolunteerMarkers()
    {
        //DROP ALL MARKERS FUNCTION
        volunteerDatabaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot volunteerprofile:dataSnapshot.getChildren())
                {

                    key=(String) volunteerprofile.child("UserID").getValue();
                    victimID=(String) volunteerprofile.child("VictimProfileID").getValue();
                    getVictimInfo();//GET NAME,PIC,JOB TITLE FROM THE VICTIM TABLE FOR THIS SPECIFIC VOLUNTEER
                    getUserInfo();//GET EMAIL AND PHONE NUMBER FROM USERS TABLE FOR THIS SPECIFIC VOLUNTEER
                    String currentuserid=SaveSharedPreference.getUserName(FindNearbyVolunteers.this);
                    if(!key.equals(currentuserid))//TO AVOID CURRENT USER BEING SHOWN AS A VOLUNTEER
                    {
                        address= (String)volunteerprofile.child("Address").getValue();
                        availabiliity=(String)volunteerprofile.child("Availability").getValue();
                        String LAT= (String) volunteerprofile.child("Latitude").getValue();
                        String LNG= (String) volunteerprofile.child("Longitude").getValue();
                        Toast.makeText(FindNearbyVolunteers.this,LAT+", "+LNG,Toast.LENGTH_SHORT).show();
                        Double Lat= Double.parseDouble(LAT);
                        Double Long= Double.parseDouble(LNG);
                        LatLng latLng = new LatLng(Lat,Long);
                        MarkerOptions markerOptions = new MarkerOptions();
                        markerOptions.position(latLng);
                        Toast.makeText(FindNearbyVolunteers.this,key+", "+victimID+", "+name+", "+jobtitle+", "+availabiliity+", "+email+", "+address,Toast.LENGTH_LONG).show();
                        //mMap.setInfoWindowAdapter(new VolunteerPopupAdapter(FindNearbyVolunteers.this,name,jobtitle,availabiliity,email,address,dp,number));
                        markerOptions.title(volunteerprofile.getKey().toString());
                        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
                        mCurrLocationMarker = mMap.addMarker(markerOptions);
                    }
                    else{
                        //IN CASE OF CURRENT USER
                            //Place current location marker
                            LatLng latLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
                            MarkerOptions markerOptions = new MarkerOptions();
                            markerOptions.position(latLng);
                            markerOptions.title("YOU");
                            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
                            mCurrLocationMarker = mMap.addMarker(markerOptions);
                }}

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

getVictimInfo() 方法:

 private void getVictimInfo()
    {
        victimDatabaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot victimProfile:dataSnapshot.getChildren())
                {
                    if(victimProfile.getKey().equals(victimID))
                    {
                        dp=(String)victimProfile.child("DP").getValue();
                        jobtitle=(String)victimProfile.child("JobTitle").getValue();
                        name=(String)victimProfile.child("Name").getValue();

                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

    }

getUserInfo() 方法

        private void getUserInfo(){
        userDatabaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot userProfile:dataSnapshot.getChildren())
                {
                    if(userProfile.getKey().equals(key))
                    {
                        email=(String)userProfile.child("Email").getValue();
                        number=(String)userProfile.child("Mobile").getValue();;

                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

我应该保存值的字符串

 DatabaseReference volunteerDatabaseReference,userDatabaseReference,victimDatabaseReference;
String dp,jobtitle="no value",name="no value";
String email="no value",number="no value",address="no value",availabiliity="no value",victimID,key;

我的数据库截图 enter image description here

您现在不能使用尚未加载的内容。换句话说,您不能简单地将 dpjobtitleemail 声明为全局变量并在 onDataChange() 方法之外使用它们,因为它总是 null 由于此方法的异步行为。这意味着当您尝试在该方法之外使用这些值时,数据尚未从数据库加载完成,这就是为什么无法访问并且您总是得到 null 这就是为什么什么都没有写的原因在你的数据库中。

一个快速解决这个问题的方法是只在 onDataChange() 方法内部使用所有这些值,或者如果你想在外部使用它们,我建议你深入异步世界并查看最后一部分我从这个 in which I have explained how it can be done using a custom callback. You can also take a look at this video 中得到了更好的理解。