androidfirebasefirebase-realtime-databaseanonymous-inner-class

How can I change variable of an outside class from anonymous inner class?


I have an ArrayList on database and I have a function getArrayList that reference the database and returns the list. The problem is that I cannot save the arraylist because I get it from inner class.

*ArrayList waiting_list is defined outside

 private ArrayList<FirebaseUser> getWaitingList (String uid){
    database.child("books").child(""+itemNum+1)
    .addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot d:dataSnapshot.getChildren()){
                if(d.getKey().equals("waiting list"));
                        GenericTypeIndicator<ArrayList<FirebaseUser>> t = new GenericTypeIndicator<ArrayList<FirebaseUser>>() {};
                        waiting_list = d.getValue(t);// this is the problem
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    return waiting_list; //I beleive that waiting_list is still null here
}

Solution

  • You're correct, the list is still null because you're never waiting for Firebase results over the network, your code is only setting a listener, then immediately returning an empty list.

    Rather than this blocking call from your method

    someList = getWaitingList (String uid);
    // use someData
    

    You should be doing something like this asynchronous call

    // Do NOT make a list variable outside of this
    getWaitingList (String uid, new Listener() {
        @Override onData(List someData) {
            // use someData, for example, update a listview 
        } 
    });
    // do NOT reference the list outside of the listener block method 
    

    That being said,

    Define an interface

    interface UserListListener {
        void onUsers(List<FirebaseUser> users);
    } 
    

    Add a parameter to the method and make it void because you'll return from the interface

    void getWaitingList (String uid, final UserListListener listener) {
       ... 
    

    And the rest of the Firebase code is maybe okay, but you're looping over things, so I think you'd want to add to a list rather than just assign one, but anyway, here's the rest of the method using the Callback

    GenericTypeIndicator<ArrayList<FirebaseUser>> t = new GenericTypeIndicator<ArrayList<FirebaseUser>>() {};
    // Move the list inside this listener 
    List<FirebaseUser> waitingList = new ArrayList<>();
    for (DataSnapshot d:dataSnapshot.getChildren()){
        if(d.getKey().equals("waiting list")) {
            waitingList = d.getValue(t);
        }
    }
    listener.onUsers(waitingList); // end of the method
    

    Then the external method call is responsible for implementation of the listener class, and getting the data.

    You'll also want to implement onCancelled ; it's good practice to implement this first because it's where you will be notified of Firebase errors - do not leave it blank