Android聊天应用SearchView无法过滤用户问题求助
问题
我在Android Studio开发的聊天应用里有一个展示所有注册用户的Fragment,想添加SearchView功能,根据输入的部分/完整名称、邮箱过滤用户,但无论输入什么查询内容,始终显示所有用户,且无运行时错误。
相关代码
菜单创建代码
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ inflater.inflate(R.menu.menu_main, menu); MenuItem item = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(item); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { if (!TextUtils.isEmpty(query.trim())){ searchUsers(query); } else { getAllUsers(); } return false; } @Override public boolean onQueryTextChange(String query) { if (!TextUtils.isEmpty(query.trim())){ searchUsers(query); } else { getAllUsers(); } return false; } }); super.onCreateOptionsMenu(menu, inflater); }
搜索用户代码
private void searchUsers(String query) { final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users"); ref.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { usersList.clear(); for (DataSnapshot dataSnapshot: snapshot.getChildren()){ ModelUsers modelUsers = dataSnapshot.getValue(ModelUsers.class); if (!modelUsers.getUid().equals(firebaseUser.getUid())){ if ((modelUsers.getName().toLowerCase()).contains(query.toLowerCase()) || (modelUsers.getEmail().toLowerCase()).contains(query.toLowerCase())) { usersList.add(modelUsers); } else { } } adapterUsers = new AdapterUsers(getActivity(), usersList); adapterUsers.notifyDataSetChanged(); recyclerView.setAdapter(adapterUsers); } } @Override public void onCancelled(@NonNull DatabaseError error) { } }); }
修复方案
问题出在两个核心点:
- 重复注册持续监听器:每次调用
searchUsers都用addValueEventListener,会新增一个永久监听数据变化的监听器,旧监听器不会自动移除,导致后续数据更新时覆盖过滤后的列表。应该改用addListenerForSingleValueEvent,仅读取一次数据完成过滤。 - Adapter更新时机错误:在遍历用户的循环内部创建并设置Adapter,会导致每遍历一个用户就更新一次列表,最终过滤逻辑被多次更新的操作打乱。必须把Adapter的初始化和设置放在循环结束后。
修复后的searchUsers代码:
private void searchUsers(String query) { final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users"); // 改用单次数据读取监听器,避免重复监听 ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { usersList.clear(); String lowerQuery = query.toLowerCase(); // 提前转小写,避免重复计算 for (DataSnapshot dataSnapshot: snapshot.getChildren()){ ModelUsers modelUsers = dataSnapshot.getValue(ModelUsers.class); // 增加判空,防止空指针 if (modelUsers != null && !modelUsers.getUid().equals(firebaseUser.getUid())){ if (modelUsers.getName().toLowerCase().contains(lowerQuery) || modelUsers.getEmail().toLowerCase().contains(lowerQuery)) { usersList.add(modelUsers); } } } // 循环结束后统一更新Adapter adapterUsers = new AdapterUsers(getActivity(), usersList); recyclerView.setAdapter(adapterUsers); // 若Adapter已初始化,也可直接调用notifyDataSetChanged,无需重复新建 // adapterUsers.notifyDataSetChanged(); } @Override public void onCancelled(@NonNull DatabaseError error) { // 可添加错误提示,比如Toast.makeText(getActivity(), "加载失败", Toast.LENGTH_SHORT).show(); } }); }
额外优化建议:
- 如果
getAllUsers方法也使用了addValueEventListener,同样要改成addListenerForSingleValueEvent - 可以复用已创建的Adapter,避免每次搜索都新建实例,提升性能
内容的提问来源于stack exchange,提问作者Carl Quartey
相关产品推荐
相关产品推荐

