Android Studio结合Firestore实现日历按日期筛选用药提醒并展示到RecyclerView
问题解决方案
该需求完全可实现,你目前的实现逻辑存在多处不合理的地方,导致筛选效果不符合预期,可按以下方案修正:
现有代码存在的问题
- 在
onBindViewHolder中通过设置View.GONE隐藏不符合条件的item的方式不规范,会导致RecyclerView出现空白占位、滚动异常等问题,且列表计数仍为全量数据长度,并未实现真正的筛选。 - 每次切换选中日期都重新调用
setAdapter重复绑定适配器,效率极低,没有必要。 - 日期对比逻辑错误:你拿
holder.StartDate.toString()(TextView的文本内容)做对比,正确的做法是直接取数据源中存储的日期字段对比,且需保证两侧日期格式完全一致,否则会出现匹配失败的问题。
修正方案
步骤1:改造适配器,新增筛选逻辑
适配器单独维护全量数据和筛选后的数据列表,不要直接使用全局的全量数据源:
public class MyMedicationAdapter extends RecyclerView.Adapter<MyMedicationAdapter.MyViewHolder> { // 存储从Firestore获取的全量用药数据 private List<medication_info> allMedicationList; // 存储筛选后待展示的用药数据 private List<medication_info> filteredList = new ArrayList<>(); // 构造方法传入全量数据 public MyMedicationAdapter(List<medication_info> allList) { this.allMedicationList = allList; } // 对外暴露的日期筛选方法,切换日期时调用 public void filterByDate(String selectedDate) { filteredList.clear(); for (medication_info info : allMedicationList) { // 直接取数据源中的日期字段对比,无需通过View获取 if (info.StartDate.equals(selectedDate)) { filteredList.add(info); } } // 通知适配器数据变更,刷新列表 notifyDataSetChanged(); } @Override public int getItemCount() { // 返回筛选后的列表长度,而非全量数据长度 return filteredList.size(); } @Override public void onBindViewHolder(@NonNull MyMedicationAdapter.MyViewHolder holder, int position) { medication_info medication_info = filteredList.get(position); holder.InventoryMeds.setText(medication_info.InventoryMeds); holder.Medication.setText(medication_info.Medication); holder.StartDate.setText(medication_info.StartDate); holder.Time.setText(medication_info.Time); // 删除原有设置可见性的逻辑,筛选后的数据全部需要展示 } // 其余ViewHolder初始化等原有代码保持不变即可 }
步骤2:修改日期选择监听逻辑
只在页面初始化时绑定一次适配器,切换日期时直接调用适配器的筛选方法即可:
// 页面初始化时仅绑定一次适配器,无需每次切换日期重复设置 myAdapter = new MyMedicationAdapter(userArrayList); recyclerView1.setAdapter(myAdapter); calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() { @Override public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) { month += 1; // 注意:此处生成的日期格式必须和Firestore中存储的StartDate字段格式完全一致 // 如果存储的日期带前导零,可使用String.format补零:String selectedDate = String.format("%02d/%02d/%d", dayOfMonth, month, year); String selectedDate = dayOfMonth + "/" + month + "/" + year; Log.d("Calendar", "Selected day change " + selectedDate); // 调用适配器筛选方法 myAdapter.filterByDate(selectedDate); } });
注意事项
- 必须保证Firestore中存储的
StartDate字段格式,和选中日期时生成的selectedDate格式完全一致,避免因格式差异导致匹配失败。如果有条件建议统一使用LocalDate对象或者时间戳做对比,比字符串对比更稳妥。 - 如果需要默认展示当前日期的用药数据,可在页面初始化、拿到Firestore全量数据后,主动调用一次
filterByDate方法传入当前日期即可。
内容的提问来源于stack exchange,提问作者Lance Quinto
相关产品推荐
相关产品推荐

