简体   繁体   中英

How to access (modify, add elements) to an ArrayList/Collection in an Inner class in java?

I've got this search function to search for specific Users using a firebase Database using GeoFire.

What i want to do :

In GeoQueryEventListener() & onKeyEntered , I want to add each key found to an ArrayList (outside onKeyEntered() ).

The problem i have :

When I print it inside the onKeyEntered() , it works. But as soon as I exit the GeoQueryEventListener() , keysGeolocated is empty

public ArrayList<User> search(GeoFire geoFire, int day, final boolean isBartender, double latitude, double longitude, double radius, double rate, double nightlyRate, double hourlyRate, final String speciality){

    keysGeolocated = new ArrayList<>();
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    root = database.getReference();
    DatabaseReference usersRef = root.child("Users");

    GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), radius);
    geoQuery.addGeoQueryEventListener(new MyGeoListener(keysGeolocated));

    System.out.println("KEYS GEOLOCATED" + keysGeolocated);

    final ArrayList<User> result = new ArrayList<>();

    for(String key : keysGeolocated){

        Query queryByLocation = usersRef.orderByKey().equalTo(key);
        DatabaseReference refToLocationQuery = queryByLocation.getRef();

        if(checkRefNull(refToLocationQuery) == true) {
            System.out.println("QUERY BY LOCATION NULL");
            continue;
        }

        Query queryByTypeOfUser  = refToLocationQuery.orderByChild("isBarTender").equalTo(isBartender);
        DatabaseReference refToTypeOfUserQuery = queryByTypeOfUser.getRef();

        if(checkRefNull(refToTypeOfUserQuery) == true) {
            System.out.println("QUERY BY TYPE NULL");
            continue;
        }
        Query queryByRate  = refToTypeOfUserQuery.orderByChild("rate").startAt(rate);
        DatabaseReference refToRateQuery = queryByRate.getRef();

        if(checkRefNull(refToRateQuery) == true) {
            System.out.println("QUERY BY RATE NULL");
            continue;
        }

        DatabaseReference finalRef = null;

        if(isBartender == true){

            if(nightlyRate == 0){
                Query queryByPrice  = refToRateQuery.orderByChild("nightlyRate").endAt(nightlyRate);
                finalRef = queryByPrice.getRef();
            }
            else if(hourlyRate == 0){
                Query queryByPrice  = refToRateQuery.orderByChild("hourlyRate").endAt(hourlyRate);
                finalRef = queryByPrice.getRef();
            }

            //TODO Impelement checks for available dates

        }
        else{
            finalRef = refToRateQuery;
        }

        finalRef.addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                if(dataSnapshot.getValue()!=null){

                    User userFound = dataSnapshot.getValue(User.class);

                    if(isBartender == true){
                        Bartender barTenderFound = (Bartender) userFound;
                        if(speciality != null){
                            if(barTenderFound.getSpeciality().contains(speciality)){
                                result.add(barTenderFound);
                            }
                        }
                        else{
                            result.add(barTenderFound);
                        }
                    }
                    else{
                        result.add(userFound);
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

    }

    return result;
}

public boolean checkRefNull(DatabaseReference ref){

    final boolean[] result = new boolean[1];
    result[0] = false;

        ref.addValueEventListener(new ValueEventListener() {


            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                System.out.println("TEST1");
                if(dataSnapshot.getValue()==null){
                    result[0] = true;
                    System.out.println("TESTTEST");
                }
                else{
                    System.out.println("TESTTEST TRUE" + dataSnapshot.getValue());
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
    });

    return result[0];
}

public void setBarTender(boolean barTender){

    this.barTender = barTender;
}
}

class MyGeoListener implements GeoQueryEventListener {

private ArrayList<String> keysGeolocated;

MyGeoListener(ArrayList<String> keysGeolocated){
    this.keysGeolocated = keysGeolocated;
}

@Override
public void onKeyEntered(String key, GeoLocation location) {
    keysGeolocated.add(key);
}

@Override
public void onKeyExited(String key) {

}

@Override
public void onKeyMoved(String key, GeoLocation location) {

}

@Override
public void onGeoQueryReady() {

}

@Override
public void onGeoQueryError(DatabaseError error) {

}
}

Make a Class which extends that listener and override all the methods

class MyGeoListener extends GeoQueryEventListener{

    private ArrayList<String> keysGeolocated;

    MyGeoListener(ArrayList<String> keysGeolocated){
          this.keysGeolocated = keysGeolocated;
    }

    @Override
    public void onKeyEntered(String key, GeoLocation location) {
        keysGeolocated.add(key);
        System.out.println("1111111111 : "+keysGeolocated);
        System.out.println("2222222222 : "+key);
    }

    @Override
    public void onKeyExited(String key) {

    }

    @Override
    public void onKeyMoved(String key, GeoLocation location) {

    }

    @Override
    public void onGeoQueryReady() {

    }

    @Override
    public void onGeoQueryError(DatabaseError error) {

    }
}

Now use this class as follows:

geoQuery.addGeoQueryEventListener(new MyGeoListener(keysGeolocated));

The immediate next call will always print no values in the list as the listener is asynchronous and takes time to fill the list.

Try putting the print inside a handler postdelayed with say 30000 milliseconds delay. You will probably see entries in the list as by then the listener events should have fired.

Since an arraylist is mutable and you are passing it's reference, the arraylist in the argument will also be modified when the listener calls.

Good luck and let me know if you still have issues.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM