0

I have a Firebase Realtime database and I would like to retreive some data and put them in an arraylist.

ArrayList<Item> itemsArray;
List<Item> itemsList;

DatabaseReference shopRef;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shop);

    itemsArray = new ArrayList<>();

    shopRef = FirebaseDatabase.getInstance().getReference();

    Query query = shopRef.child("shop");

    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                Item item = new Item();
                item.setLogo(snapshot.child("Logo").getValue().toString());
                item.setName(snapshot.child("Name").getValue().toString());
                item.setDescription(snapshot.child("Description").getValue().toString());
                itemsArray.add(item);  //itemsArray is full

            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
        }
    });

    itemsList = itemsArray; // itemsArray is null
}

The problem is that after the listener, it looks simple to fix but I don’t understand why the arraylist is null.

The database works properly

The Item class works properly

  • Data is loaded from Firebase (and most modern cloud APIs) asynchronously, because it takes time to get data from the internet. While the data is being loaded, your main code continues to execute, and thus your `itemsList = itemsArray;` runs before any of the `itemsArray.add(item)` has ever executed. --- The solution for this is always the same: any code that needs the data from the database, has to be inside `onDataChange`, be called from there, or be synchronized in some other way. See the questions I linked for more on this, and examples. – Frank van Puffelen Jan 03 '22 at 16:04
  • If you understand Kotlin, this article, [How to read data from Firebase Realtime Database using get()?](https://medium.com/firebase-tips-tricks/how-to-read-data-from-firebase-realtime-database-using-get-269ef3e179c5) will help. – Alex Mamo Jan 03 '22 at 16:17

1 Answers1

1

When you add a Listener to Query, you don't immediately get the data back in the array list. The meaning of what you have written is:

  • Make a query on Realtime Database,
  • When a data change event is received (or when the listener is added) call the onDataChanged(DataSnapshot) function

So what you need is a callback when you get the data in the future.

That means you won't be getting the data immediately where you did:

itemsList = itemsArray; // itemsArray is null

Instead do something like:

class MyActivity extends AppCompatActivity {
   private final List<Item> itemsArrayList = new ArrayList<>();

   @Override

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shop);
    
        shopRef = FirebaseDatabase.getInstance().getReference();
    
        Query query = shopRef.child("shop");
    
        query.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                List<Item> snapshotItems = new ArrayList<>();
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    Item item = new Item();
                    item.setLogo(snapshot.child("Logo").getValue().toString());
                    item.setName(snapshot.child("Name").getValue().toString());
                    item.setDescription(snapshot.child("Description").getValue().toString());

                    snapshotItems.add(item);
                }
                // Calling this function will add the data back to the list
                MyActivity.this.onItemsObtained(snapshotItems);
            }
    
            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
    }

    public void onItemsObtained(List<Item> items) {
        itemsArrayList.clear(); // To remove old Data
        itemsArrayList.addAll(items);
        
        // Continue your own logic...
    }

}
Jugal Mistry
  • 160
  • 1
  • 9