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

如何从外部方法访问RecyclerView.ViewHolder中的MediaPlayer实现滑动停止播放

解决方案

第一步:优化ViewHolder内MediaPlayer的生命周期逻辑

原有代码每次调用setData都会新建MediaPlayer实例,ViewHolder复用时旧实例没有释放,会出现内存泄漏、多个音频同时播放的问题,先修改ViewHolder代码:

public class ViewHolder extends RecyclerView.ViewHolder {
    RoundedImageView imageView;
    TextView username;
    ImageButton buttonInfo;
    MediaPlayer mediaPlayer;
    public ViewHolder(@NonNull @NotNull View itemView) {
        super(itemView);
        imageView = itemView.findViewById(R.id.itemCardStackView);
        username = itemView.findViewById(R.id.textViewUsername_stackView);
        buttonInfo = itemView.findViewById(R.id.buttonToInfo_stackView);
    }

    void setData(Users data) {
        // 先释放旧的MediaPlayer实例
        releaseMediaPlayer();
        mediaPlayer  = new MediaPlayer();
        if (!data.getAudioIntro().equals("")) {
            try {
                mediaPlayer.setDataSource(data.getAudioIntro());
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        booleanCallBack.checkAudio(true);
                        username.setText(data.getUsername());
                        Glide.with(context).load(data.getAvatar()).into(imageView);
                    }
                });
                mediaPlayer.prepareAsync();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }          
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!data.getAudioIntro().equals("")) {
                    if (mediaPlayer.isPlaying())
                        mediaPlayer.pause();
                    else {
                        mediaPlayer.start();
                    }
                } else {
                    Toast.makeText(context, "No Voice intro", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    // 新增停止播放的公共方法
    public void stopPlay() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
            // 如需停止后回到进度起点可添加以下代码
            // mediaPlayer.seekTo(0);
        }
    }

    // 新增释放MediaPlayer资源的公共方法
    public void releaseMediaPlayer() {
        if (mediaPlayer != null) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

第二步:在Adapter中实现stopMediaplayer方法

根据你的布局场景选择对应实现即可:

场景1:卡片堆叠布局一次仅展示1张可见卡片

在Adapter中添加成员变量记录当前活跃的ViewHolder,后续直接调用其停止方法即可:

public class YourAdapter extends RecyclerView.Adapter<ViewHolder> {
    // 新增成员变量记录当前活跃的ViewHolder
    private ViewHolder currentActiveHolder;
    private List<Users> dataList;

    // ...原有其他Adapter逻辑不变

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        // 绑定数据时更新当前活跃的ViewHolder记录
        currentActiveHolder = holder;
        holder.setData(dataList.get(position));
    }

    @Override
    public void onViewRecycled(@NonNull ViewHolder holder) {
        super.onViewRecycled(holder);
        // ViewHolder回收时释放资源
        holder.releaseMediaPlayer();
        if (currentActiveHolder == holder) {
            currentActiveHolder = null;
        }
    }

    public void stopMediaplayer() {
        if (currentActiveHolder != null) {
            currentActiveHolder.stopPlay();
        }
    }
}

场景2:同屏有多个可见卡片

遍历所有已挂载的ViewHolder逐个停止播放即可:

public void stopMediaplayer() {
    for (int i = 0; i < recyclerView.getChildCount(); i++) {
        View childView = recyclerView.getChildAt(i);
        ViewHolder holder = (ViewHolder) recyclerView.getChildViewHolder(childView);
        holder.stopPlay();
    }
}

额外优化建议

  • Activity销毁时记得调用Adapter的资源释放逻辑,避免MediaPlayer后台继续播放造成内存泄漏
  • 建议把ViewHolder内的点击事件通过接口回调抛给Activity处理,避免ViewHolder持有Context引用造成内存泄漏

内容的提问来源于stack exchange,提问作者Lộc Trần Phước

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 15:45:03