You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView中CountDownTimer切换ViewType后闪烁问题解决咨询

解决CountDownTimer切换ViewType时的闪烁问题

问题根源

闪烁的核心原因有两个:

  1. RecyclerView复用ViewHolder时,旧的CountDownTimer未被取消,新Timer和旧Timer同时更新同一个TextView,导致数值跳变。
  2. 每次绑定ViewHolder时,没有先设置当前实时的倒计时数值,而是等Timer第一次onTick触发(延迟1秒),期间会显示之前的旧值,造成闪烁。

具体修复步骤

1. 给ViewHolder添加Timer引用并管理生命周期

在ExamListV2ActiveItemViewHolder里添加成员变量保存当前Timer,绑定前先取消旧Timer:

public class ExamListV2ActiveItemViewHolder extends RecyclerView.ViewHolder {
    public final ItemBinding binding;
    public CountDownTimer currentTimer; // 保存当前运行的Timer

    public ExamListV2ActiveItemViewHolder(ItemBinding binding) {
        super(binding.getRoot());
        this.binding = binding;
    }
}

2. 绑定ViewHolder时先取消旧Timer,再设置实时数值

修改绑定逻辑,先取消旧Timer,计算当前剩余时间并直接设置文本,最后启动新Timer:

// 先取消旧Timer,避免多个Timer同时更新UI
if (holder.currentTimer != null) {
    holder.currentTimer.cancel();
    holder.currentTimer = null;
}

long currentTimeMillis = System.currentTimeMillis();
long timeUntilStart = startDate.getTime() - currentTimeMillis;
long timeUntilEnd = endDate.getTime() - currentTimeMillis;

if (timeUntilStart > 0) {
    // 先设置当前实时的倒计时数值,避免等待onTick的1秒延迟
    long seconds = (timeUntilStart / 1000) % 60;
    long minutes = (timeUntilStart / (1000 * 60)) % 60;
    long hours = (timeUntilStart / (1000 * 60 * 60));
    holder.binding.tvRemainingTime.setText(String.format("%02d Hour: %02d min :%02d sec", hours, minutes, seconds));

    // 创建并启动新Timer,同时保存到ViewHolder
    holder.currentTimer = new CountDownTimer(timeUntilStart, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            long sec = (millisUntilFinished / 1000) % 60;
            long min = (millisUntilFinished / (1000 * 60)) % 60;
            long hr = (millisUntilFinished / (1000 * 60 * 60));
            holder.binding.tvRemainingTime.setText(String.format("%02d Hour: %02d min :%02d sec", hr, min, sec));
        }

        @Override
        public void onFinish() {
            holder.binding.btnJoin.setVisibility(View.VISIBLE);
            holder.binding.tvStarts.setText(context.getResources().getString(R.string.exam_starts_in));
            
            // 先设置结束阶段的实时数值
            long secEnd = (timeUntilEnd / 1000) % 60;
            long minEnd = (timeUntilEnd / (1000 * 60)) % 60;
            long hrEnd = (timeUntilEnd / (1000 * 60 * 60));
            holder.binding.tvRemainingTime.setText(String.format("%02d Hour %02d Min %02d Sec", hrEnd, minEnd, secEnd));

            // 创建结束阶段的Timer,保存到ViewHolder
            holder.currentTimer = new CountDownTimer(timeUntilEnd, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {
                    long sec = (millisUntilFinished / 1000) % 60;
                    long min = (millisUntilFinished / (1000 * 60)) % 60;
                    long hr = (millisUntilFinished / (1000 * 60 * 60));
                    holder.binding.tvRemainingTime.setText(String.format("%02d Hour %02d Min %02d Sec", hr, min, sec));
                }

                @Override
                public void onFinish() {
                    holder.binding.tvRemainingTime.setText(context.getResources().getString(R.string.exam_ended));
                    holder.currentTimer = null; // 结束后清空引用
                }
            };
            holder.currentTimer.start();
        }
    };
    holder.currentTimer.start();
}

3. 回收ViewHolder时取消Timer

在RecyclerView.Adapter里重写onViewRecycled方法,确保ViewHolder被回收时取消Timer:

@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
    super.onViewRecycled(holder);
    if (holder instanceof ExamListV2ActiveItemViewHolder) {
        ExamListV2ActiveItemViewHolder activeHolder = (ExamListV2ActiveItemViewHolder) holder;
        if (activeHolder.currentTimer != null) {
            activeHolder.currentTimer.cancel();
            activeHolder.currentTimer = null;
        }
    }
}

额外注意点

  • 直接用System.currentTimeMillis()获取当前时间,比创建Date对象更高效。
  • 确保startDate和endDate是有效时间戳,避免计算出负数导致Timer异常。

内容的提问来源于stack exchange,提问作者Shahriar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:04:59