我应该更换数据结构,还是对FirebaseRecyclerAdapter进行过滤?
高校App公告列表FirebaseRecyclerAdapter自动过滤实现方案
实现思路:通过给FirebaseRecyclerAdapter注册数据变化观察者,在每次数据集更新时自动触发过滤逻辑,无需手动调用。
步骤1:提前获取当前登录学生的属性作为过滤基准
在页面初始化时,先从当前登录学生的节点读取department、year、language三个字段值,存储为全局常量,作为后续过滤的匹配规则。步骤2:改造FirebaseRecyclerAdapter实现Filterable接口
在Adapter中重写getFilter方法,过滤逻辑设置为仅保留目标院系、目标年级、目标语言同时和当前学生属性完全匹配的公告数据,示例代码如下:
public class AnnouncementAdapter extends FirebaseRecyclerAdapter<Announcement, AnnouncementAdapter.AnnounceViewHolder> implements Filterable { private List<Announcement> mFullList; // 存储全量公告数据 private String currentDept; private String currentYear; private String currentLanguage; // 构造方法里传入学生的三个属性值 public AnnouncementAdapter(@NonNull FirebaseRecyclerOptions<Announcement> options, String dept, String year, String language) { super(options); this.currentDept = dept; this.currentYear = year; this.currentLanguage = language; // 初始化时同步全量数据 mFullList = new ArrayList<>(getSnapshots()); } @Override protected void onBindViewHolder(@NonNull AnnounceViewHolder holder, int position, @NonNull Announcement model) { // 原有绑定视图的逻辑保持不变 } @NonNull @Override public AnnounceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { // 原有创建ViewHolder的逻辑保持不变 } @Override public Filter getFilter() { return announcementFilter; } private Filter announcementFilter = new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { List<Announcement> filteredList = new ArrayList<>(); for (Announcement item : mFullList) { // 三个属性全部匹配才加入结果集 if (item.getTargetDept().equals(currentDept) && item.getTargetYear().equals(currentYear) && item.getTargetLanguage().equals(currentLanguage)) { filteredList.add(item); } } FilterResults results = new FilterResults(); results.values = filteredList; return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { // 更新列表为过滤后的结果 getSnapshots().clear(); getSnapshots().addAll((List<Announcement>) results.values); notifyDataSetChanged(); } }; // 数据更新时同步全量列表 public void updateFullList() { mFullList.clear(); mFullList.addAll(getSnapshots()); } }
- 步骤3:注册数据变化观察者自动触发过滤
在初始化Adapter之后,给Adapter注册AdapterDataObserver,重写onChanged方法,每次数据集有更新时先同步全量数据,再触发过滤,示例代码如下:
// 观察者定义为成员变量,方便后续销毁时移除 private RecyclerView.AdapterDataObserver dataObserver; private AnnouncementAdapter adapter; // 初始化Adapter,传入当前学生的三个属性 adapter = new AnnouncementAdapter(options, currentDept, currentYear, currentLanguage); recyclerView.setAdapter(adapter); // 注册数据变化观察者 dataObserver = new RecyclerView.AdapterDataObserver() { @Override public void onChanged() { super.onChanged(); // 先同步最新的全量数据 adapter.updateFullList(); // 自动触发过滤 adapter.getFilter().filter(""); } }; adapter.registerAdapterDataObserver(dataObserver); // 页面销毁时移除观察者避免内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (adapter != null && dataObserver != null) { adapter.unregisterAdapterDataObserver(dataObserver); adapter.stopListening(); } }
注意:如果后续公告数据量大幅增长,也可以考虑在Firebase数据库侧添加复合索引,直接通过服务端查询过滤数据减少客户端计算量,当前客户端过滤方案适合公告量不大、无隐私风险的场景。
内容的提问来源于stack exchange,提问作者Kamel Fakih
相关产品推荐
相关产品推荐

