Firebase 通过多个查询搜索并添加到 RecyclerView Android Studio

Posted

技术标签:

【中文标题】Firebase 通过多个查询搜索并添加到 RecyclerView Android Studio【英文标题】:Firebase search by multiple queries and add to RecyclerView Android Studio 【发布时间】:2021-10-05 18:00:02 【问题描述】:

我正在尝试使用 Firebase 在消息传递应用程序中复制搜索功能,并将结果显示在 RecyclerView 中。

我想按顺序返回相同 recyclerview 中名字、用户名或姓氏以搜索输入文本开头的用户。

我能够通过其中一个孩子成功搜索,在这种情况下,我正在搜索用户的名字,但我真的不知道如何添加用户名和姓氏的结果,并且在这样的一种没有重复的方式(例如,如果我搜索“A”,则名“Anna”和姓“Albury”的用户不会出现两次。

感谢所有帮助。

Activity searchUsers 方法:

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 方法

    @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) 
        
    );

好友类:

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;

我的数据库示例:

【问题讨论】:

我想你可能对这篇文章感兴趣,How to filter Firestore data cheaper?。 除此之外,为什么说“Anna”和“Albury”出现了两次 @AlexMamo 目前没有。我的意思是说,部分困难在于找到一个解决方案,以便其名字和姓氏都对应于搜索输入的用户不会在 recyclerview 中显示两次 这是不可能的。实时数据库中没有全文搜索。因此,如果您正在搜索“A”,此名称不会出现在“John Alex”的结果中。 @AlexMamo 嗨,Alex,感谢您的回复。我知道不可能在字符串中搜索。我正在寻找一种解决此问题的方法,通过有效地搜索 3 次,一次用于名字,一次用于姓氏,一次用于用户名,并在单个回收器视图中整理生成的用户。 【参考方案1】:

根据你上一条评论:

我正在寻找一种解决此问题的方法,即有效搜索 3 次,一次搜索名字,一次搜索姓氏,一次搜索用户名,然后在单个 RecyclerView 中整理结果用户。

在这种情况下,您应该执行三个不同的查询并使用Tasks.whenAllSuccess() 方法收集所有结果:

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
    
);

但请记住,为避免重复,仅当列表不存在时才将名称添加到列表中。然后简单地将列表传递给适配器,并在 RecyclerView 中仅显示结果而不显示重复。

【讨论】:

如果您认为我的回答对未来的 Firebase 开发者也有帮助,也请考虑投上一票(▲)。我真的很感激。谢谢!

以上是关于Firebase 通过多个查询搜索并添加到 RecyclerView Android Studio的主要内容,如果未能解决你的问题,请参考以下文章

如何将多个图像上传到Firebase存储并返回多个downloadURL

Firebase 中的搜索查询

Swift - 如何在 Firebase 上将排序查询创建为降序?

如何使用 swift 有条件地向 Firebase Firestore 中的查询添加另一个过滤器?

如何通过 BigQuery 从 Firebase 分析中获取事件转换

如何将图表添加到 Firebase?