Android RecyclerView使用MediaPlayer多音频同时播放如何解决
解决方案
核心逻辑
用成员变量标记当前正在播放的列表项位置,切换播放项前先停止上一个MediaPlayer的播放任务,同时刷新上下两个播放项的按钮UI,避免状态错乱。
改造后代码
1. 新增标记位成员变量
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { // 全局唯一MediaPlayer实例,保证同一时间只有一个音频播放 private final MediaPlayer mediaPlayer = new MediaPlayer(); // 标记位:记录当前正在播放的列表项下标,默认-1代表无正在播放的音频 private int currentPlayingPosition = -1;
2. 修改onBindViewHolder逻辑
不要在onBindViewHolder中直接操作MediaPlayer重置/设置数据源,将音频加载逻辑移到点击事件中:
@Override public void onBindViewHolder(@NonNull MyAdapter.ViewHolder viewHolder, int position) { // 绑定阶段先根据当前播放标记设置按钮显示状态 viewHolder.play.setImageResource(currentPlayingPosition == position ? R.drawable.pause : R.drawable.play); viewHolder.play.setOnClickListener(v -> { int clickPosition = viewHolder.getAdapterPosition(); // 防止列表项已被移除时的无效点击 if (clickPosition == RecyclerView.NO_POSITION) return; // 点击的是正在播放的项,切换暂停/播放状态 if (currentPlayingPosition == clickPosition) { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); viewHolder.play.setImageResource(R.drawable.play); } else { mediaPlayer.start(); viewHolder.play.setImageResource(R.drawable.pause); } return; } // 点击的是新项:先停止上一个播放,重置状态 if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.reset(); // 刷新上一个播放项的按钮UI int lastPlayPos = currentPlayingPosition; currentPlayingPosition = -1; notifyItemChanged(lastPlayPos); } // 加载新音频并播放 try { mediaPlayer.setDataSource(item.get(clickPosition).getAudio()); mediaPlayer.prepare(); mediaPlayer.start(); // 更新标记位和当前项按钮状态 currentPlayingPosition = clickPosition; viewHolder.play.setImageResource(R.drawable.pause); } catch (IOException e) { e.printStackTrace(); currentPlayingPosition = -1; viewHolder.play.setImageResource(R.drawable.play); } }); }
注意事项
- 页面销毁时需调用
mediaPlayer.release()释放MediaPlayer资源,避免内存泄漏 - 若音频文件过大或为网络音频,建议将
prepare()替换为prepareAsync(),配合OnPreparedListener回调完成后再调用start(),避免阻塞主线程 - 可给MediaPlayer设置
OnCompletionListener,音频播放完成后重置currentPlayingPosition为-1并刷新对应项UI
内容的提问来源于stack exchange,提问作者ghazalia
相关产品推荐
相关产品推荐

