RecyclerView音频播放冲突问题求助:多音频同时播放
解决RecyclerView音频同时播放的问题
我来帮你搞定这个多个音频同时播放的bug!问题出在你的Adapter里每次点击播放按钮都会创建一个新的MediaPlayer实例,之前正在播放的MediaPlayer没有被停止和释放,所以就会出现两首音频同时响的情况。
下面是具体的修复方案,我会一步步说明关键修改点:
核心修改思路
- 维护一个全局的
MediaPlayer实例(或者在Adapter里保留当前播放的实例),每次播放新音频前先停止并释放旧的实例 - 记录当前正在播放的音频位置,适配RecyclerView的ViewHolder复用特性,避免按钮状态错乱
- 正确管理MediaPlayer的生命周期,及时释放资源
修改后的完整代码
public class AdapterSong extends RecyclerView.Adapter<AdapterSong.viewHolder> { Context context; List<ModelSong> model; String url_audio; MediaPlayer mediaplayer; // 记录当前正在播放的音频位置 private int currentPlayingPosition = -1; public AdapterSong(Context context, List<ModelSong> model) { this.context = context; this.model = model; } @NonNull @Override public AdapterSong.viewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rec_song, parent, false); return new AdapterSong.viewHolder(view); } @Override public void onBindViewHolder(@NonNull final AdapterSong.viewHolder holder, final int position) { final ModelSong data = model.get(position); holder.tittle.setText(data.getTittle()); // 根据当前播放位置更新按钮状态 if (currentPlayingPosition == position) { holder.play.setVisibility(View.GONE); holder.stop.setVisibility(View.VISIBLE); } else { holder.play.setVisibility(View.VISIBLE); holder.stop.setVisibility(View.GONE); } holder.play.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { // 先停止并释放之前的MediaPlayer if (mediaplayer != null) { mediaplayer.stop(); mediaplayer.release(); mediaplayer = null; } url_audio = "http://kanoonmedia.ir/files/sorod/" + data.getFile(); mediaplayer = new MediaPlayer(); mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaplayer.setDataSource(url_audio); mediaplayer.setLooping(true); mediaplayer.prepare(); // 更新当前播放位置并刷新UI int previousPosition = currentPlayingPosition; currentPlayingPosition = position; notifyItemChanged(previousPosition); notifyItemChanged(currentPlayingPosition); holder.play.setVisibility(View.GONE); holder.stop.setVisibility(View.VISIBLE); mediaplayer.start(); } catch (IllegalArgumentException | SecurityException | IllegalStateException | IOException e) { e.printStackTrace(); } } }); holder.stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mediaplayer != null) { mediaplayer.stop(); mediaplayer.release(); mediaplayer = null; } // 重置当前播放位置并刷新UI currentPlayingPosition = -1; notifyItemChanged(position); } }); } @Override public int getItemCount() { return model.size(); } // 页面销毁时调用,释放MediaPlayer资源避免内存泄漏 public void releaseMediaPlayer() { if (mediaplayer != null) { mediaplayer.stop(); mediaplayer.release(); mediaplayer = null; currentPlayingPosition = -1; } } public class viewHolder extends RecyclerView.ViewHolder { TextView tittle; CircleImageView play, stop; public viewHolder(View itemView) { super(itemView); tittle = itemView.findViewById(R.id.txt_tittle_song); play = itemView.findViewById(R.id.img_play_song); stop = itemView.findViewById(R.id.img_stop_song); } } }
关键修改点说明
- 新增
currentPlayingPosition变量:用来记录当前正在播放的音频在列表中的位置,解决ViewHolder复用导致的按钮状态显示错误 - 播放前检查并释放旧实例:每次点击新的播放按钮时,先停止并释放之前的MediaPlayer,确保同一时间只有一个音频在播放
- 主动刷新UI状态:播放或停止操作后,调用
notifyItemChanged刷新对应item的按钮显示,保证状态同步 - 新增资源释放方法:在Activity/Fragment的
onDestroy生命周期中调用releaseMediaPlayer,避免MediaPlayer内存泄漏
另外,额外提一句:如果你的音频播放需求比较复杂,建议考虑使用ExoPlayer替代原生MediaPlayer,它在多音频管理、生命周期适配方面会更专业稳定哦!
内容的提问来源于stack exchange,提问作者Farhad Abdoli
相关产品推荐
相关产品推荐

