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

Android中RecyclerView滚动时SeekBar进度异常问题求助

RecyclerView音频SeekBar滚动异常问题解决方案

核心原因

RecyclerView的ViewHolder复用机制导致:滚动时被回收的ViewHolder重新绑定数据,若未正确同步当前播放的音频进度,会默认显示SeekBar的最大值(即末尾);再次滚动回来时,ViewHolder重新绑定到正确的播放状态,进度恢复正常。


具体解决方案

1. 维护全局播放状态记录

创建单例类统一管理当前播放的音频信息,避免ViewHolder复用后状态丢失:

public class AudioPlayManager {
    private static AudioPlayManager instance;
    private String currentAudioId; // 当前播放的音频唯一标识
    private int currentProgress;   // 当前播放进度
    private int totalDuration;     // 音频总时长
    private boolean isPlaying;     // 播放状态

    private AudioPlayManager() {}

    public static AudioPlayManager getInstance() {
        if (instance == null) {
            instance = new AudioPlayManager();
        }
        return instance;
    }

    // 更新播放状态
    public void updatePlayState(String audioId, int progress, int duration, boolean playing) {
        currentAudioId = audioId;
        currentProgress = progress;
        totalDuration = duration;
        isPlaying = playing;
    }

    // 提供getter方法获取状态
    public String getCurrentAudioId() { return currentAudioId; }
    public int getCurrentProgress() { return currentProgress; }
    public int getTotalDuration() { return totalDuration; }
    public boolean isPlaying() { return isPlaying; }
}

2. 绑定ViewHolder时同步播放状态

在onBindViewHolder方法中,根据全局状态判断当前列表项是否为正在播放的音频,同步SeekBar和图标状态:

@Override
public void onBindViewHolder(@NonNull AudioViewHolder holder, int position) {
    AudioMessage message = messageList.get(position);
    AudioPlayManager playManager = AudioPlayManager.getInstance();

    // 匹配当前播放音频,同步进度和图标
    if (message.getId().equals(playManager.getCurrentAudioId())) {
        holder.seekBar.setMax(playManager.getTotalDuration());
        holder.seekBar.setProgress(playManager.getCurrentProgress());
        holder.playBtn.setImageResource(playManager.isPlaying() ? R.drawable.ic_pause : R.drawable.ic_play);
    } else {
        // 非播放状态,重置SeekBar和图标
        holder.seekBar.setProgress(0);
        holder.playBtn.setImageResource(R.drawable.ic_play);
    }

    // 播放按钮点击逻辑
    holder.playBtn.setOnClickListener(v -> {
        if (message.getId().equals(playManager.getCurrentAudioId()) && playManager.isPlaying()) {
            // 暂停当前音频
            pauseCurrentAudio();
            playManager.updatePlayState(message.getId(), playManager.getCurrentProgress(), playManager.getTotalDuration(), false);
            holder.playBtn.setImageResource(R.drawable.ic_play);
        } else {
            // 切换播放新音频
            stopCurrentAudio();
            startAudio(message.getAudioPath(), message.getId());
            int duration = getAudioDuration(message.getAudioPath());
            playManager.updatePlayState(message.getId(), 0, duration, true);
            holder.playBtn.setImageResource(R.drawable.ic_pause);
        }
    });
}

3. 实时同步播放进度到全局状态

在音频播放的进度回调中,同时更新全局状态,确保ViewHolder复用后能获取到最新进度:

private Handler progressHandler = new Handler();
private Runnable progressRunnable = new Runnable() {
    @Override
    public void run() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            int currentPos = mediaPlayer.getCurrentPosition();
            int totalDur = mediaPlayer.getDuration();
            // 更新全局状态
            AudioPlayManager.getInstance().updatePlayState(currentAudioId, currentPos, totalDur, true);
            // 更新当前显示的ViewHolder进度(可选,若需要实时刷新)
            if (currentPlayingViewHolder != null) {
                currentPlayingViewHolder.seekBar.setProgress(currentPos);
            }
            progressHandler.postDelayed(this, 100);
        }
    }
};

4. 处理ViewHolder回收时的资源清理

在onViewRecycled方法中,清理当前播放ViewHolder的引用和进度更新任务,避免内存泄漏:

@Override
public void onViewRecycled(@NonNull AudioViewHolder holder) {
    super.onViewRecycled(holder);
    AudioPlayManager playManager = AudioPlayManager.getInstance();
    if (messageList.get(holder.getAdapterPosition()).getId().equals(playManager.getCurrentAudioId())) {
        progressHandler.removeCallbacks(progressRunnable);
        currentPlayingViewHolder = null;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 09:45:05