Erjon
Erjon

Reputation: 930

Java List<Object> size

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.

Upvotes: 0

Views: 119

Answers (4)

Haider Malik
Haider Malik

Reputation: 1771

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
                    }
                });

Upvotes: 1

DHAVAL A.
DHAVAL A.

Reputation: 2321

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();

}

Upvotes: 0

Martin Nowosad
Martin Nowosad

Reputation: 826

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

Upvotes: 3

Shadov
Shadov

Reputation: 5592

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.

Upvotes: 3

Related Questions