如何实现RecyclerView条目倒计时到期后移至列表底部并修复现有报错
问题修复方案
核心错误原因
- 现有逻辑不符合需求:你调用了
ItemArrayList.remove直接删除到期条目,自然无法实现移动到底部的效果 - 位置获取时机错误:先操作列表再调用
holder.adapterPosition(),此时拿到的位置已经无效,极易出现数组越界、空指针等崩溃 - 变量作用域错误:全局共享
remTime变量,多个条目同时倒计时会出现时间串位 - 复用逻辑隐患:条目滑出屏幕被复用后,旧的倒计时没有完全销毁,会出现时间错乱、内存泄漏问题
修复后代码
onBindViewHolder逻辑
@Override public void onBindViewHolder(@NonNull Holder holder, int position) { // 先销毁当前holder已有的倒计时,避免复用错乱 if (holder.timer != null) { holder.timer.cancel(); holder.timer = null; } ItemDet item = ItemArrayList.get(position); long expireTimestamp = item.getCategoryTime().toDate().getTime(); long currentTime = System.currentTimeMillis(); long leftTime = expireTimestamp - currentTime; // 已经到期的条目直接显示到期状态 if (leftTime <= 0) { holder.itemView.setEnabled(false); holder.item_time_h.setText("Time up!"); return; } holder.timer = new CountDownTimer(leftTime, 1000) { public void onTick(long millisUntilFinished) { // 用局部变量存储剩余时间,避免多个条目串值 long seconds = millisUntilFinished / 1000; long minutes = seconds / 60; long hours = minutes / 60; long days = hours / 24; String remTime; // 优化判断逻辑,避免重复赋值 if (days > 0) { remTime = days + "d, " + hours % 24 + "h"; } else if (hours > 0) { remTime = hours % 24 + "h:" + minutes % 60 + "m"; } else if (minutes > 0) { remTime = minutes % 60 + "m:" + seconds % 60 + "s"; } else { remTime = seconds % 60 + "s"; } holder.item_time_h.setText(remTime); } public void onFinish() { holder.itemView.setEnabled(false); holder.item_time_h.setText("Time up!"); // 先获取有效位置,再操作列表 int currentPos = holder.getAdapterPosition(); // 校验位置合法性,避免崩溃 if (currentPos != RecyclerView.NO_POSITION && currentPos < ItemArrayList.size()) { // 取出到期条目 ItemDet expiredItem = ItemArrayList.remove(currentPos); // 添加到列表末尾 ItemArrayList.add(expiredItem); // 直接通知条目移动,不需要额外调用remove和范围更新 notifyItemMoved(currentPos, ItemArrayList.size() - 1); } } }.start(); }
增加条目回收时的倒计时销毁逻辑
在Adapter中新增如下方法,避免内存泄漏:
@Override public void onViewRecycled(@NonNull Holder holder) { super.onViewRecycled(holder); if (holder.timer != null) { holder.timer.cancel(); holder.timer = null; } }
内容的提问来源于stack exchange,提问作者Avni Krtigya
相关产品推荐
相关产品推荐

