0

I have a list in java android:

List<FirebaseData> GetListMap(String data){

    final List<FirebaseData> Elements = new ArrayList<>();

    FirebaseDatabase database = FirebaseDatabase.getInstance();

    mShiftReference = database.getReference("Map/Data/").child(data);

    mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            for (DataSnapshot child: dataSnapshot.getChildren()) {

                Elements.add(child.getValue(FirebaseData.class));
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            // Failed to read value
            Log.w("data", "Failed to read value.", error.toException());
        }
    });

    return Elements;
}

When i try to exctract the size of the array it returns 0, for example:

int size = GetListMap("2019-06-24").size();

Or i can't exctract any property.

Any idea what i'm doing wrong.

2
  • 3
    GetListMap returns a List<FirebaseData>, but you're assigning its result to an int. What's actually going on? (And this looks like it's adding a listener for when a change happens later, but it's not actually clear whether you've waited for the change to happen.) Commented Jun 25, 2019 at 21:04
  • Sorry @LouisWasserman you are right, it should be int size = GetListMap("2019-06-24").size(); Commented Jun 25, 2019 at 21:06

4 Answers 4

3

First, I assume you mean int size = GetListMap("2019-06-24").size(); (size at the end).

Second, you are assigning a list to the returned value, it's an empty list at this moment. Then you attach a listener that waits for an event (data change), if that happens, then and only then it will add an element to the list.

Basically, your list is always gonna be empty, unless the data change events occur. You need to trigger an event and then check the list, it should change it's size.

Sign up to request clarification or add additional context in comments.

1 Comment

I just did but unfortunately nothing changed. Anyway thank you for responding +1.
3

You're returning your Elements collection before it actually gets data from your Firebase Database due to the asynchronous nature of your listener.

You'd have to define a callback if you want to get an update after your async code is done

List<FirebaseData> GetListMap(String data){

final List<FirebaseData> Elements = new ArrayList<>();

FirebaseDatabase database = FirebaseDatabase.getInstance();

mShiftReference = database.getReference("Map/Data/").child(data);

mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        System.out.println("About to fill Elements");
        for (DataSnapshot child: dataSnapshot.getChildren()) {

            Elements.add(child.getValue(FirebaseData.class));
        }
        System.out.println("Elements is filled");

    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        // Failed to read value
        Log.w("data", "Failed to read value.", error.toException());
    }
});
System.out.println("Returning Elements with size: " + Elements.size());
return Elements;
}
int x = GetListMap("...").size();
System.out.println("x: +" x);

``

That code would result in following output:

  1. Returning Elements with size 0
  2. x: 0
  3. About to fill Elements
  4. Elements is filled

Btw please use camelCase for your methods and variables whenever you are developing in Java

Comments

1

You are returning the list before firebase has finished adding everything. You want to create an interface method for the function.

in the class create an interface:

public interface Complete{
    void taskCompleted(List<FirebaseData> list);
}

then assign it to your method (now returns void as the interface will be producing the result):

public void GetListMap(String data, Complete completeListener){

. . . .

mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        for (DataSnapshot child: dataSnapshot.getChildren()) {
            Elements.add(child.getValue(FirebaseData.class));
        }

        completeListener.taskComplete(Elements);
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
            completeListener.taskComplete(null);
        }
    });

}

To use method:

GetListMap("data", new Complete() {
                    @Override
                    public void taskCompleted(List<FirebaseData> list) {
                        //do what you want with the list object
                    }
                });

Comments

0

First of all your GetListMap method contains firebase database call which of-course asynchronous call. Means you are getting data on separate thread. So the line below this calls execute before firebase process query response. So it is not possible to get returned value from method which contains asynchronous functions.

So to get exact what you want, you will have to wait for query response.

Refer below code to achieve what you want.

// Avoiding return type with this method.
void GetListMap(String data){

    final List<FirebaseData> Elements = new ArrayList<>();

    FirebaseDatabase database = FirebaseDatabase.getInstance();

    mShiftReference = database.getReference("Map/Data/").child(data);

    mListener = mShiftReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            for (DataSnapshot child: dataSnapshot.getChildren()) {

                Elements.add(child.getValue(FirebaseData.class));
            }

            // Use below method to update data inside your views.
            // This method will only called once firebase query return response.
            updateUI(Elements); 
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            // Failed to read value
            Log.w("data", "Failed to read value.", error.toException());
        }
    });

    // Now this method is void so need to return any value.
    //return Elements;
}

Example of updateUI(...) method.

void updateUI(List<FirebaseData> elements) {

   int size = elements.size();

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.