Firebase caching destroys children’s order

I am creating a chat application, and the last chat message is called up in the chat / chat list to show it just like in any other messaging application.

However, when the chat is open, all chat messages are retrieved using messagesDbRef.orderByChild("time").addChildEventListener(...), and the callback is onChildAddedinstantly called for the last chat message (the one that was received in the chat list) that has the maximum value for the field time, while all other messages are then retrieved from the database in increasing order of field values time.

In the example of messages marked from 1 to 5, this leads to their addition to the RecyclerView in the order of [5, 1, 2, 3, 4], the last being 5.

However, when the chat is closed and opens again, the order is correct [1, 2, 3, 4, 5].

How can i fix this? Is there a way to force all messages to reload when opening a chat?

EDIT:

Here is a minimal working example that reproduces the problem:

Data in the real-time database:

testing: {
    abc123: {
        name: "first",
        time: 100
    },
    abc456: {
        name: "second",
        time: 200
    },
    abc789: {
        name: "third",
        time: 300
    }
}

the code:

final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("testing");

ref.child("abc789").addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Stuff lastStuff = dataSnapshot.getValue(Stuff.class);
        Log.i("Testing", "retrived child " + lastStuff.name + " with time " + lastStuff.time);

        ref.orderByChild("time").addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                Stuff stuff = dataSnapshot.getValue(Stuff.class);
                Log.i("Testing", "name: " + stuff.name + ", time: " + stuff.time);
            }

            ...
});

This leads to the output:

I / Testing: returned child third with a age of 300

I / Testing: name: third, time: 300

I / Testing: name: first, time: 100

I / Testing: name: second, time: 200

However , I noticed that if I use addListenerForSingleValueEventinstead addValueEventListener, the problem will disappear and the order will be correct. I probably just have a listener open somewhere in my application.

In any case, I do not think that the cached value should subsequently affect the search order.

+1
1

, Firebase . Firebase: child_added ?.

, , Firebase. , :

ref.child("abc789").addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Log.i("Testing", "retrieved child " + dataSnapshot.child("name").getValue() + " with time " + dataSnapshot.child("time").getValue());

        ref.orderByChild("time").addChildEventListener(new ChildEventListener() {
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                Log.i("Testing", "ChildAdded: key "+dataSnapshot.getKey()+" name " + dataSnapshot.child("name").getValue() + ", time " + dataSnapshot.child("time").getValue()+" previousKey "+s);
            }

            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                Log.i("Testing", "ChildChanged: key "+dataSnapshot.getKey()+" name " + dataSnapshot.child("name").getValue() + ", time " + dataSnapshot.child("time").getValue()+" previousKey "+s);
            }

            public void onChildRemoved(DataSnapshot dataSnapshot) {
                Log.i("Testing", "ChildRemoved: key "+dataSnapshot.getKey()+" name " + dataSnapshot.child("name").getValue() + ", time " + dataSnapshot.child("time").getValue());
            }

            public void onChildMoved(DataSnapshot dataSnapshot, String s) {
                Log.i("Testing", "ChildMoved: key "+dataSnapshot.getKey()+" name " + dataSnapshot.child("name").getValue() + ", time " + dataSnapshot.child("time").getValue()+" previousKey "+s);
            }

            public void onCancelled(DatabaseError error) {
                System.err.println("Listener was cancelled "+error.toString());
            }

        });

    }

, logs:

  • ( s ),
  • , onChildAdded

:

01-07 10: 10: 23,859 3706-3706/? I/: 300

01-07 10: 10: 23,869 3706-3706/? I/Testing: ChildAdded: abc789 , 300 previousKey null

01-07 10: 10: 23,932 3706-3706/? I/Testing: ChildAdded: abc123 , 100 previousKey null

01-07 10: 10: 23,933 3706-3706/? I/Testing: ChildAdded: abc456 , 200 previousKey abc123

previousKey/s , , , UI/list . [ onChildAdded() ] (https://firebase.google.com/docs/reference/android/com/google/firebase/database/ChildEventListener.html#onChildAdded(com.google.firebase.database.DataSnapshot, java.lang.String )):

  • .
  • abc789, : [abc789]
  • abc123. , : [abc123, abc789]
  • abc456, Key abc123. abc123, : [abc123, abc456, abc789]

, , onChildAdded, , , , .

+1

Source: https://habr.com/ru/post/1691166/


All Articles