0

I'm attempting to implement a search feature for an app which populates attendees from Firebase. The 'meeting' object has an integer list, containing user IDs, and the application goes to firebase and creates 'user' objects for each user attending that particular meeting.

I'm trying to include a search feature which will help filter and find users based on their name.

Here's where the user objects are being retrieved, and added to the recyclerview as chips:

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

    Integer selectedUser = mMeeting.getUsers().get(position);
    String selectedUserString = String.valueOf(selectedUser);

    FirebaseFirestore db = FirebaseFirestore.getInstance();
    String user = FirebaseAuth.getInstance().getCurrentUser().getUid();
    DocumentReference userDocRec = db.collection("users/"+user+"/clients").document(selectedUserString);

    userDocRec.get()
            .addOnSuccessListener((documentSnapshot) -> {
                        if (documentSnapshot.exists()) {
                            User thisUser = documentSnapshot.toObject(User.class);
                            String name = String.valueOf(thisUser.getFirstName()
                                    + " " + String.valueOf(thisUser.getSurName()));
                            String dateOfBirth = thisUser.getDateOfBirth();

                                Chip chip = ((Chip) holder.itemView);
                                chip.setChipText(name);
                                chip.setVisibility(View.VISIBLE);
                                chip.setChecked(mMeeting.getAttended().contains(selectedUser));
                                chip.setOnCloseIconClickListener(view -> {
                                    Toast.makeText(mContext, name + " - DOB: " + dateOfBirth, Toast.LENGTH_SHORT).show();
                                });

                            userMap.put(position, thisUser);
                        }
                    }
            ).addOnFailureListener((e) -> {
                Toast.makeText(mContext, "Cannot load user", Toast.LENGTH_SHORT).show();
            }
    );

I have tried a pretty hacky solution whereby the adapter and recyclerviews are reloaded every time the search feature is interacted with, and a for loop only populates chips where the user name matches or includes the search term:

mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                searchFilter = s;
                AttendanceAdapter2 adapter = new AttendanceAdapter2(mMeeting, mContext,
                        (m) -> ((Callback<Meeting>) getActivity()).update(m));
                recyclerView.setAdapter(adapter);
                return false;
            }
        @Override
        public boolean onQueryTextChange(String s) {
            searchFilter = s;
            AttendanceAdapter2 adapter = new AttendanceAdapter2(mMeeting, mContext,
                    (m) -> ((Callback<Meeting>) getActivity()).update(m));
            recyclerView.setAdapter(adapter);
            return false;
        }
    });



    if (InterventionAttendanceFragment.searchFilter == "" ||
 name.toLowerCase().contains(InterventionAttendanceFragment.searchFilter.toLowerCase())){
                                Chip chip = ((Chip) holder.itemView);
                                chip.setChipText(name);
                                chip.setVisibility(View.VISIBLE);
                                chip.setChecked(mMeeting.getAttended().contains(selectedUser));

                                chip.setOnCloseIconClickListener(view -> {
                                    Toast.makeText(mContext, name + " - DOB: " + dateOfBirth, Toast.LENGTH_SHORT).show();
                                });
                            }

Its not a great solution, and is very resource heavy, going via firebase every time, and also leaves gaps in the recyclerview, for the chips that don't match the search term.

I have found a few nice solutions, but they rely on the 'users' being populated via a list, and due to the existing infrastructure, and nature of the application, I can't change it too much, to start running off lists rather than firebase:

How to filter a RecyclerView with a SearchView

https://www.androidhive.info/2017/11/android-recyclerview-with-search-filter-functionality/

Any help or pointers, and possible alternative solutions or libraries would be much appreciated!

Currently running Android Studio 3.1.4

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
brett clement
  • 43
  • 1
  • 5

1 Answers1

0

Firebase Firestore database is quite limited in query capabilities ,But you can use cloud functions and perform the process of filtering on server side instead .I have run to this problem many times but unfortunately firestore currently not supporting such complex queries yet its better than its sister Realtime database.

Odai A. Ali
  • 845
  • 3
  • 8
  • 23