多个(嵌套的)ValueEventListener在firebase实时数据库中不能用于

时间:2018-05-21 10:51:42

标签: java android firebase firebase-realtime-database fatal-error

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

用户(包含用户的登录信息,例如电子邮件,密码移动电话号码等)

VictimProfiles(包含基本个人资料信息,如个人资料照片字符串,姓名,职位和用户表中相应的用户ID)

VolunteerProfiles(包含地址,纬度,经度,可用性时间以及相应的UserID和VictimProfileID(Firebase生成的那些))

在我的Google地图活动中,我需要在每个志愿者的位置以及当前使用该应用的用户上放置标记,并在自定义信息窗口中显示志愿者的必要信息, 但是,如下面的代码所示,当我尝试从志愿者表的ValueEventListener中访问VictimProfile和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) {

            }
        });
    }

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

1 个答案:

答案 0 :(得分:0)

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

这个问题的快速解决方法是仅在null方法中使用所有这些值,或者如果你想在外面使用它们,我建议你深入到异步世界,看看我的anwser的最后一部分从这个 post 中我已经解释了如何使用自定义回调来完成它。您还可以查看此 video ,以便更好地理解。