Daan
Daan

Reputation: 73

Firebase onChildAdded returns null data and then onChildChanged after updating child

I'm trying to do some basic Firebase operations however, the childEventListener is not behaving as expected.

I have a list of restaurant orders which I display in a list using a Firebase query and ChildEventListener. The query is used to get all orders that are un-cooked i.e WHERE cooked = false.

FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
mDatabaseReference = mFirebaseDatabase.getReference().child(UUID + "/" + outletID + "/orders");
Query query = mDatabaseReference.orderByChild("cooked").equalTo(false);

mChildEventListener = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {

            Log.e(TAG, "ChildEventListener() - onChildAdded - " + dataSnapshot.getKey());

            Order order = dataSnapshot.getValue(Order.class);
            mAdapter.addOrder(order);
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

            Log.e(TAG, "ChildEventListener() - onChildChanged - " + dataSnapshot.getKey());

            Order order = dataSnapshot.getValue(Order.class);
            mAdapter.updateOrder(order);
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

            Log.e(TAG, "ChildEventListener() - onChildRemoved - " + dataSnapshot.getKey() + ", exist - " + dataSnapshot.exists());

            Order order = dataSnapshot.getValue(Order.class);
            mAdapter.removeOrder(order);
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            Log.e(TAG, "ChildEventListener() - onChildMoved - " + dataSnapshot.getKey());
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

            Log.w(TAG, "ChildEventListener : onCancelled - ", databaseError.toException());
        }
    };

    query.addChildEventListener(mChildEventListener);

This works fine and it pulls the right data out.

I have another list which gets all the orders that are cooked i.e WHERE cooked = true. I use a one time event listener for this and shows the correct data as expected.

Query query = mDatabaseReference.orderByChild("cooked").equalTo(true);

In my list of cooked orders, when user taps on a order, it is meant to update the cooked flag back to "false" and appear in the list of un-cooked orders. It is done using the following setValue() method.

mDatabaseReference.child(order.getPushID()).child("cooked").setValue(false);

Issue 1

When I load the activity and there are no un-cooked orders, this is where the problem occurs. As I tap on a cooked order, the Firebase database updates the cooked flag as expected however, the onChildAdded() is called as expected but the order object data is null. I also get onChildChanged call after that with the order object data.

When I carry on tapping cooked orders, it calls onChildAdded() once with correct data as expected. So technically, I am missing the first order that was cooked due to the null data.

If I load the activity that has 1 or more un-cooked orders and I tap on a cooked order, the onChildAdded() gets called as expected and updates the list of un-cooked orders.

I tried changing the setValue() to updateChildren() but still same outcome.

Upvotes: 2

Views: 801

Answers (1)

Yev Kanivets
Yev Kanivets

Reputation: 1800

Usually, such an issue is reproduced with Firebase when you write several properties of one object using several setValue operations. I suggest a following scenario:

  1. Order is added to \orders, onChildAdded is called, but this is empty because of its cooked property is false.
  2. Cooked property is set to false. onChildUpdated is called with order you need.

Maybe this is not what you do, but just how it's implemented under the hood. Maybe you could just use onChildUpdated?

Upvotes: 3

Related Questions