Firebase search by multiple queries and add to RecyclerView Android Studio

Viewed 424

I'm attempting to replicate a search function in a messaging app with Firebase and display the results in a RecyclerView.

I would like to return users whose firstname, username, or lastname start with the search input text in the same recyclerview, in that order.

I am able to successfully search by one of the children, in this case I'm searching for a user's first name, but I'm really stuck as to how to add the results from the username and lastname, and in such a way that there is no duplication (e.g. if I search "A", a user with firstname "Anna" and lastname "Albury" doesn't appear twice.

Any and all help appreciated, thanks.

Activity searchUsers method:

private void searchUsers(String s){
    searchInput = search_users.getText().toString();


    FirebaseRecyclerOptions<Friends> retrievedFriends = new FirebaseRecyclerOptions.Builder<Friends>()
            .setQuery(FriendsRef.orderByChild("refFirstName")
                    .startAt(searchInput).endAt(searchInput+"\uf8ff"), Friends.class)
            .build();

    FirebaseRecyclerAdapter<Friends, FriendsViewHolder> adapter =
            new FirebaseRecyclerAdapter<Friends, FriendsViewHolder>(retrievedFriends) {
                @Override
                protected void onBindViewHolder(@NonNull @NotNull FriendsViewHolder holder, int position, @NonNull @NotNull Friends model) {
                    final String usersIDs = getRef(position).getKey();
                    UsersRef.child(usersIDs).addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull @NotNull DataSnapshot dataSnapshot) {
                            if (dataSnapshot.child("Details").hasChild("profileImage")) {
                                String userImage = dataSnapshot.child("Details").child("profileImage").child("imageUrl").getValue().toString();
                                String profileFirstName = dataSnapshot.child("Details").child("firstname").getValue().toString();
                                String profileLastName = dataSnapshot.child("Details").child("lastname").getValue().toString();
                                String profileStatus = dataSnapshot.child("Details").child("status").getValue().toString();

                                String profileName = profileFirstName + " " + profileLastName;
                                holder.userName.setText(profileName);
                                holder.userStatus.setText(profileStatus);
                                Picasso.get().load(userImage).into(holder.profileImage);
                            } else {
                                String profileFirstName = dataSnapshot.child("Details").child("firstname").getValue().toString();
                                String profileLastName = dataSnapshot.child("Details").child("lastname").getValue().toString();

                                String profileName = profileFirstName + " " + profileLastName;

                                holder.userName.setText(profileName);
                                
                            }
                        }

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

                        }
                    });
                }

                @NonNull
                @NotNull
                @Override
                public FriendsViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
                    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.users_message_layout, parent, false);
                    return new FriendsViewHolder(view);
                }
            };

    myFriendsList.setAdapter(adapter);
    adapter.startListening();

}

Activity onCreate method

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_message);

    //default function
    myFriendsList = (RecyclerView) findViewById(R.id.new_message_friends_list);
    myFriendsList.setLayoutManager(new LinearLayoutManager(this));

    mAuth = FirebaseAuth.getInstance();
    currentUserID = mAuth.getCurrentUser().getUid();

    FriendsRef = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserID).child("Friends");
    UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");

    //search function
    search_users = findViewById(R.id.new_message_search_edittext);


    search_users.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            int length = search_users.length();

            if (length > 0) {
                searchUsers(s.toString());

            } else {
                cancelSearch();
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });
}

Friends class:

public class Friends {
public String firstName, lastName, status, image, uid;

public Friends (){

}

public Friends(String firstName, String lastName, String status, String image, String uid) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.status = status;
    this.image = image;
    this.uid = uid;
}

public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}

public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}

public String getStatus() {return status;}
public void setStatus(String lastName) {this.status = status;}

public String getImage() {return image;}
public void setImage(String image) {this.image = image;}

public String getUid() {return uid;}
public void setUid(String uid) {this.uid = uid;}

}

Sample of my database:

enter image description here

1 Answers

According to your last comment:

What I'm looking for is a way to get around this by effectively search three times, once for first names, once for last names, and once for usernames, and collate the resulting users in a single RecyclerView.

In this case, you should perform three different queries and collect all the results using Tasks.whenAllSuccess() method:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query firstQuery = rootRef...
Query secondQuery = rootRef...
Query thirdQuery = rootRef...

Task firstTask = firstQuery.get();
Task secondTask = secondQuery.get();
Task thirdTask = thirdQuery.get();

Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask, thirdTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
    @Override
    public void onSuccess(List<Object> list) {
         //Do what you need to do with your list
    }
});

But remember, to avoid duplicates, add a name to the list only if it does not exist. Then simply pass the list to an adapter, and display only the results without duplicates in a RecyclerView.

Related