Android开发:如何对RecyclerView中的元素按日期排序且不丢失对应文本
疑问解答
- 如何保证排序时日期和文本的关联不丢失?
不要用两个独立List存储关联数据,新建实体类将同一条目的日期、文本绑定为一个对象,所有操作基于对象集合进行,就不会出现关联错位的问题。 - 排序应该在哪个环节执行?
必须在数据库读取完全部数据、传入Adapter之前执行,Adapter加载完成后再排序完全没有必要,还会导致页面重复渲染,影响性能和用户体验。
具体实现步骤
1. 新建绑定数据的实体类
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class ReminderItem { private final String text; private final String dateStr; private final long dateTimestamp; public ReminderItem(String text, String dateStr) { this.text = text; this.dateStr = dateStr; // 构造时直接将日期字符串转为时间戳,避免排序时重复转换消耗性能 SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()); try { Date date = sdf.parse(dateStr); this.dateTimestamp = date != null ? date.getTime() : 0; } catch (ParseException e) { e.printStackTrace(); this.dateTimestamp = 0; // 日期解析失败时默认排最前,可自行调整 } } public String getText() { return text; } public String getDateStr() { return dateStr; } public long getDateTimestamp() { return dateTimestamp; } }
2. 修改数据库读取逻辑,增加排序处理
// 全局声明变量 private mainRowAdapter rAdapter; private final List<ReminderItem> reminderItemList = new ArrayList<>(); // 数据库监听部分修改为如下逻辑 dbf.child("Reminders").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { reminderItemList.clear(); // 遍历所有数据转为实体类对象 for(DataSnapshot child2 : snapshot.getChildren()) { String text = ""; String date = ""; for(DataSnapshot tChild : child2.getChildren()) { if ("text".equals(tChild.getKey())) { text = tChild.getValue(String.class); } if ("date".equals(tChild.getKey())) { date = tChild.getValue(String.class); } } if (text != null && date != null && !text.isEmpty() && !date.isEmpty()) { reminderItemList.add(new ReminderItem(text, date)); } } // 按日期升序排序,要降序的话调换o1和o2的位置即可 Collections.sort(reminderItemList, new Comparator<ReminderItem>() { @Override public int compare(ReminderItem o1, ReminderItem o2) { return Long.compare(o1.getDateTimestamp(), o2.getDateTimestamp()); } }); // 优化Adapter初始化逻辑,避免每次数据变更都新建Adapter if (rAdapter == null) { rAdapter = new mainRowAdapter(MainActivity.this, reminderItemList); rv.setLayoutManager(new LinearLayoutManager(MainActivity.this)); rv.setAdapter(rAdapter); } else { rAdapter.notifyDataSetChanged(); } } @Override public void onCancelled(@NonNull DatabaseError error) { // 可按需添加错误处理逻辑 } });
3. 修改Adapter逻辑
// Adapter的构造方法改为接收实体类集合 public class mainRowAdapter extends RecyclerView.Adapter<mainRowAdapter.ViewHolder> { private final Context context; private final List<ReminderItem> itemList; public mainRowAdapter(Context context, List<ReminderItem> itemList) { this.context = context; this.itemList = itemList; } // ...其他代码不变 @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { ReminderItem item = itemList.get(position); holder.reminder.setText(item.getText()); holder.date.setText(item.getDateStr()); } @Override public int getItemCount() { return itemList.size(); } }
原有排序错误的原因
直接对字符串格式的日期排序,默认是按字典序比较的,比如1.12.2021的第二个字符是.,ASCII码小于数字0,所以会排在10.09.2021前面,完全不符合日期的实际先后顺序,必须转为时间戳或者Date对象后再比较。
内容的提问来源于stack exchange,提问作者Spectator
相关产品推荐
相关产品推荐

