如何对RecyclerView的ArrayList交易数据源按日期分组并仅展示单次日期头
原代码问题排查
你写的代码存在三个明显问题:
- 索引越界:循环条件
i <= txnList.size()会触发数组越界异常,安卓列表的索引从0开始,最大可取到txnList.size()-1 - 逻辑错误:内层循环遍历从0到当前位置的所有条目,当前条目和自身比对时就会命中相等条件,直接把日期控件隐藏,导致所有条目都不会显示日期
- 性能冗余:在条目绑定逻辑里写双层循环,列表长度较大时会出现明显卡顿,完全不需要全量比对相同日期
实现方案
你拿到的API返回数据已经按时间倒序排列,同日期的条目是连续的,只要在onBindViewHolder中把当前条目和上一条的日期做比对即可,只有当前是列表第一条,或者和上一条日期不一致的时候才显示日期。
注意要先把createdAt字段的ISO格式时间戳提取出纯日期部分,避免同日期但时分秒不同导致比对失败。
- 先写日期转换的工具方法
// 将ISO格式的时间戳转换为yyyy-MM-dd格式的日期字符串 private String formatDate(String isoTime) { try { SimpleDateFormat isoSdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.CHINA); Date date = isoSdf.parse(isoTime); SimpleDateFormat dateSdf = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); return dateSdf.format(date); } catch (ParseException e) { e.printStackTrace(); return ""; } }
- 修改RecyclerView.Adapter的
onBindViewHolder逻辑
@Override public void onBindViewHolder(@NonNull TransactionHolder holder, int position) { Transaction currentTxn = txnList.get(position); String currentDate = formatDate(currentTxn.getCreatedAt()); // 判断当前条目是否是对应日期组的第一个条目 boolean showDate = false; if (position == 0) { showDate = true; } else { String lastDate = formatDate(txnList.get(position - 1).getCreatedAt()); if (!currentDate.equals(lastDate)) { showDate = true; } } // 控制日期控件显示状态 if (showDate) { holder.txnDate.setVisibility(View.VISIBLE); holder.txnDate.setText(currentDate); } else { holder.txnDate.setVisibility(View.GONE); } // 剩余其他控件绑定逻辑 holder.txnType.setText(currentTxn.getTransactionType()); holder.txnAmount.setText(String.valueOf(currentTxn.getTransactionAmount())); }
- 可选:如果你的列表没有默认按时间排序,绑定到Adapter之前先做一次排序即可
// 按时间倒序排列,最新的交易在前 Collections.sort(txnList, (o1, o2) -> o2.getCreatedAt().compareTo(o1.getCreatedAt()));
内容的提问来源于stack exchange,提问作者steveOS
相关产品推荐
相关产品推荐

