0

I was checking with Firebase real-time database pagination for my following data and find a strange behaviour.

Consider below data in the server and user can add the list to it from the client side:

"USER1" : {
    "-LLmMMPQZNNkpNkIgTpv" : {
      "id" : 1001,
      "name" : "PERSON1001"
    },
    "-LLmPja-ku3bVPUvbA73" : {
      "id" : 1002,
      "name" : "PERSON1002"
    },
    "-LLmPjdPvC82jnL1D6h2" : {
      "id" : 1003,
      "name" : "PERSON1003"
    },
    "-LLmPjgCq-2D4sldLHY6" : {
      "id" : 1004,
      "name" : "PERSON1004"
    },
    "-LLmPjiyZpm41wMa9t37" : {
      "id" : 1005,
      "name" : "PERSON1005"
    },
    "-LLmPjllgr-1ZKjR-u35" : {
      "id" : 1006,
      "name" : "PERSON1006"
    },
    "-LLmPjoS1pqhhKsiiHf8" : {
      "id" : 1007,
      "name" : "PERSON1007"
    },
    "-LLmPjqyY8-mJRy4L-so" : {
      "id" : 1008,
      "name" : "PERSON1008"
    },
    "-LLmPjtXwLslDQ6T9s8X" : {
      "id" : 1009,
      "name" : "PERSON1009"
    },
    "-LLmPjw25hnojgjHRlvj" : {
      "id" : 1010,
      "name" : "PERSON1010"
    },
    "-LLmPjyk3pG13CeOvMxJ" : {
      "id" : 1011,
      "name" : "PERSON1011"
    },
    "-LLmPk0X83DahACj4sCC" : {
      "id" : 1012,
      "name" : "PERSON1012"
    },
    "-LLmPk2vkUlimmvqI7aI" : {
      "id" : 1013,
      "name" : "PERSON1013"
    },
    "-LLmPk5YXhPVKHSTBnW2" : {
      "id" : 1014,
      "name" : "PERSON1014"
    },
    "-LLmPk806MCTpnxRs_62" : {
      "id" : 1015,
      "name" : "PERSON1015"
    },
    "-LLmPkATgrrguNt4iEyn" : {
      "id" : 1016,
      "name" : "PERSON1016"
    },
    "-LLmPkD82ua0YHoqatOV" : {
      "id" : 1017,
      "name" : "PERSON1017"
    },..,..,..
}

..........

public class Database {

private String TAG = Database.class.getSimpleName();
private FirebaseDatabase database;
private int pagingCounter = 10;
private int totalCount = 0;
private int totalItemsToLoad;
private Query query;
private int createNewCounter = 2001;

public Database(){
    database = FirebaseDatabase.getInstance();
}

private DatabaseReference getDatabaseReference(){
    return  database.getReference("EMPLOYEE").child("USER1").getRef();
}

private Query getQueryIntial(){
  return  getDatabaseReference().orderByChild("id").limitToFirst(pagingCounter);
}

private Query getReferenceFromRange(int start){
    return  getDatabaseReference().orderByChild("id").startAt(start).endAt(9999).limitToFirst(pagingCounter);
}

public void getPages(){
    Query myRef = getQueryIntial();
    getDatabase(myRef);
}

private void getNextPage(int id) {
    getDatabase(getReferenceFromRange(id));
}

public void getDatabase(final Query q) {
    this.query = q;
    totalItemsToLoad=totalItemsToLoad+pagingCounter;
    final ArrayList<Integer> ids = new ArrayList();
    query.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
            Person person = dataSnapshot.getValue(Person.class);
            if(person!= null) {
                Log.d(TAG, "ONCHILDADDED " + dataSnapshot);
                ids.add(person.getId());
            }
            totalCount=totalCount+1;
            if(totalCount>=totalItemsToLoad)
            {
                query.removeEventListener(this);
                int id = Collections.max(ids);
                getNextPage(id);
            }
        }

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

        }

        @Override
        public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

        }

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

        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}

public void createNew() {
    String push = getDatabaseReference().push().getKey();
    Person person = new Person();
    person.setValue(createNewCounter);
    createNewCounter=createNewCounter+1;
    getDatabaseReference().child(push).setValue(person).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
            if(!task.isSuccessful()) {
                Exception e = task.getException();
                if (e != null) {
                    e.printStackTrace();
                }
            }
        }
    });
}

}

But the problem arise when adding the next persons from client side here i added pageid from client side with id from 2001...., then the paginating results in

 //1st page
 CHILD_ADDED: { -LLmMMPQZNNkpNkIgTpv: {name=PERSON1001, id=1001} }
 CHILD_ADDED: { -LLmPja-ku3bVPUvbA73: {name=PERSON1002, id=1002} }
 CHILD_ADDED: { -LLmPjdPvC82jnL1D6h2: {name=PERSON1003, id=1003} }
 CHILD_ADDED: { -LLmPjgCq-2D4sldLHY6: {name=PERSON1004, id=1004} }
 CHILD_ADDED: { -LLmPjiyZpm41wMa9t37: {name=PERSON1005, id=1005} }
 CHILD_ADDED: { -LLmPjllgr-1ZKjR-u35: {name=PERSON1006, id=1006} }
 CHILD_ADDED: { -LLmPjoS1pqhhKsiiHf8: {name=PERSON1007, id=1007} }
 CHILD_ADDED: { -LLmPjqyY8-mJRy4L-so: {name=PERSON1008, id=1008} }
 CHILD_ADDED: { -LLmPjtXwLslDQ6T9s8X: {name=PERSON1009, id=1009} }
 CHILD_ADDED: { -LLmPjw25hnojgjHRlvj: {name=PERSON1010, id=1010} }
 //2nd page query from 1010  to 9999 to get first 10 perso ns
 CHILD_ADDED: { -LLmPjw25hnojgjHRlvj: {name=PERSON1010, id=1010} }
 CHILD_ADDED: { -LLmOIlxQ_v2dSDSKgQ8: {name=PERSON2001, id=2001} }
 CHILD_ADDED: { -LLmOIq4IHOT_LEYbpLt: {name=PERSON2002, id=2002} }
 CHILD_ADDED: { -LLmOItgo5jG7dNTmfIR: {name=PERSON2003, id=2003} }
 CHILD_ADDED: { -LLmReS7j6Gtz7Q_4LPQ: {name=PERSON2004, id=2004} }
 CHILD_ADDED: { -LLmReUhQtB6xiTOfufE: {name=PERSON2005, id=2005} }
 CHILD_ADDED: { -LLmReXPmHlHj8Ai0gow: {name=PERSON2006, id=2006} }
 CHILD_ADDED: { -LLmReZlWyCI1C4u-2-0: {name=PERSON2007, id=2007} }
 CHILD_ADDED: { -LLmRebJx6-DGemO_F34: {name=PERSON2008, id=2008} }
 CHILD_ADDED: { -LLmRedpz5mCOc365Pvu: {name=PERSON2009, id=2009} }
 //3nd page
 CHILD_ADDED: { -LLmRedpz5mCOc365Pvu: {name=PERSON2009, id=2009} }

But if no child is added from the client side the results works correctly.

user3926701
  • 313
  • 1
  • 5
  • 18

1 Answers1

1

That's the expected behaviour. onChildAdded() method will be called for each child node matching your query. So if you have 2009 items, onChildAdded() method will be called 2009 times. Most important thing is that this method is also called everytime a new child is added. This also means that you're adding a new child listener each time a new child is added. So if you submit two persons, you have two listeners and your onChildAdded() will get called twice for each child person (once for each listener). Then when you submit a another one, it will add a third listener. And so on.

The solution for this problem is to detach the previous listener before attaching a new one. Here is the official documentation regarding detaching listeners.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • next page is listened only after removing the previous listener – user3926701 Sep 07 '18 at 09:00
  • You can also do it this way. – Alex Mamo Sep 07 '18 at 09:34
  • The problem in your question was when the next persons from client side is added and the answer for this behaviour is in my answer above. As you have only added the database structure and the `ChildEventListener` which is added on a single query, it's hard for me to predict why your entire pagination system doesn't work. – Alex Mamo Sep 07 '18 at 09:48
  • Thank you for your response, after id=1010 getting id=2001 as the 2nd item, query is to get first 10 items between 1010 to 9999 (my db has data with 1010 .. to 2000) all other value between 1010 and 2001 is skipped. – user3926701 Sep 07 '18 at 09:48
  • Please see my comment above. – Alex Mamo Sep 07 '18 at 09:52
  • Take a look at the accepted answer from this [post](https://stackoverflow.com/questions/37711220/firebase-android-pagination). – Alex Mamo Sep 07 '18 at 11:43
  • Is there everything alright, have you solved the issue? – Alex Mamo Sep 08 '18 at 06:50
  • Not yet solved the problem arises when using with persistence enabled for firebase. – user3926701 Sep 08 '18 at 12:52
  • This sounds as a another problem. In order to follow the rules of this comunity, please post another fresh question using a [MCVE](https://stackoverflow.com/help/mcve), so me and other users can help you. – Alex Mamo Sep 09 '18 at 10:16