Home > Software design >  Android: best practice for nested recyclerview linked to cloud firestore
Android: best practice for nested recyclerview linked to cloud firestore

Time:03-30

I currently use a nested RecyclerView with an SQLite Database. However, I am currently switching to firebase, using Cloud Firestore as a database.

My setup is:

  • the Firestore database setup is: Users -> Houses -> Rooms -> Tasks
  • vertical rv = rooms, horizontal rv = tasks
  • one model for the vertical rv, one model for the horizontal rv
  • as vertical rv I am using FirestoreRecyclerAdapter
  • inside its onbindviewholder I am calling:
    DocumentSnapshot snapshot = getSnapshots().getSnapshot(verticalPosition);

    String roomId = snapshot.getId();
  • with the Id I am queuing for the horizontal array list (tasks), which is located inside the Firestore reference "room":
if (currentUser != null) {
        String userID = currentUser.getUid();
        userRef = fdb.collection("users").document(userID);
        houseRef = userRef.collection("houses").document("house0");
        roomRef = houseRef.collection("rooms").document(roomId);

            roomRef.get().addOnCompleteListener(tasksnap -> {
                if (tasksnap.isSuccessful()) {
                    DocumentSnapshot document = tasksnap.getResult();
                    if (document.exists()) {

                        VerticalModel room = document.toObject(VerticalModel.class);
                        if (room != null) {
                            ArrayList<HorizontalModel> tasks = room.getArrayList();

                            hAdapter = new HorizontalRecyclerViewAdapter(context, new ArrayList<>(),
                                    verticalPosition, listener, cleanInter);
                            holder.view.rvHorizontal.setHasFixedSize(true);
                            holder.view.rvHorizontal.setLayoutManager(new LinearLayoutManager(context,
                                    LinearLayoutManager.HORIZONTAL, false));

                            holder.view.rvHorizontal.setAdapter(hAdapter);
                            holder.view.rvHorizontal.setNestedScrollingEnabled(false);

                            holder.updateContents(tasks, hAdapter);
                        }
                    }
                }
            });
        }

Instead of one array list per room with all tasks, I will switch to one document for one tasks.

However, I am experiencing many Firestore read calls, probably as the onbind method is called a couple of times.

So if there are any experts: Is there a better approach? Using 2 Firestore adapters did not work for me, unfortunately.

Maybe it is possible to force firebase to read from the local cache all the time and only when the user exits the app, it update the changes?

CodePudding user response:

According to your first comment:

the number of reads and if there is a better way to implement the second rv

And the second comment:

Free users can only add 5 rooms, each with 5 tasks. Paid users will mostly add around 8 rooms, each with around 10 to 20 tasks.

The simplest option I can think of would be to use an array type field in each Room object that can hold all Task objects. Since it will exist only a few Task objects, you can easily add them to a single document. In this way, you only have to pay a single read for displaying a room together with all tasks.

If you're wondering how to map an array of custom objects into a List, please read the following article:

  • Related