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

Java 多个(嵌套)ValueEventListener在android firebase实时数据库中不工作,java,android,firebase,firebase-realtime-database,fatal-error,Java,Android,Firebase,Firebase Realtime Database,Fatal Error,我正在处理的项目在firebase实时数据库中有3个“表”,即: 用户(包含用户的登录信息,如电子邮件、密码、手机号码等) VictinProfiles(包含基本配置文件信息,如配置文件pic字符串、名称、职务和用户表中相应的用户ID) 志愿者档案(包含地址、纬度、经度、可用性时间以及相应的用户ID和VictorProfileID(由Firebase生成的)) 在我的谷歌地图活动中,我需要在每个志愿者以及当前使用该应用程序的用户的位置上放置标记,并在自定义的信息窗口中显示志愿者的必要信息, 但是

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

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

VictinProfiles(包含基本配置文件信息,如配置文件pic字符串、名称、职务和用户表中相应的用户ID)

志愿者档案(包含地址、纬度、经度、可用性时间以及相应的用户ID和VictorProfileID(由Firebase生成的))

在我的谷歌地图活动中,我需要在每个志愿者以及当前使用该应用程序的用户的位置上放置标记,并在自定义的信息窗口中显示志愿者的必要信息, 但是,如下面的代码所示,当我尝试从志愿者表的ValueEventListener中访问VictinProfile和Users表时,他们的数据不会写入我正在写入的公共字符串。我知道这听起来很复杂,但是看看代码,你就会明白我的意思了

    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) {

            }
        });
    }
getVictiminInfo()方法:

getUserInfo()方法

应该保存值的字符串

 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;
我的数据库截图

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


这个问题的一个快速解决方法是只在
onDataChange()
方法内部处理所有这些值,或者如果您想在外部使用它们,我建议您深入异步世界,并从中查看我的anwser的最后一部分,其中我解释了如何使用自定义回调来完成。你也可以看看这个,以便更好地理解。

谢谢,我不会想到的!!我会调查一下,然后尝试另一种方法。非常感谢!你认为我的回答对你有帮助吗?这很有意义,所以是的。给了我一个新的思路,所以如果你认为我的答案对你有帮助,请考虑点击点击箭头左边的复选标记来接受它。应该把颜色改成绿色。谢谢恐怕我又卡住了。我尝试将所有数据库调用放在单独的、独立的函数中,在这些函数中,数据被提取到局部变量中,然后被提取到全局列表中,但问题仍然存在。只有对数据库的第一次调用起作用,其他调用甚至没有启动。我尝试将此作为异步问题的解决方法(尝试将我的DB调用顺序化,而不是尝试在它们之间跳转)。有什么想法吗?
        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;