设置MediaPlayer的OnCompletionListener后,如何复用按钮播放音频?
解决MediaPlayer释放后重新播放崩溃的问题
嘿,这个问题我太熟了!你现在遇到的崩溃,核心原因是MediaPlayer调用release()后,原来的实例就彻底失效了,不能再复用它调用start()。咱们来一步步修复你的代码:
问题分析
你当前的代码有两个关键问题:
- 每次点击按钮都重复设置
OnCompletionListener,这没必要而且可能引发意外 - 播放完成后调用
mp1.release()销毁了MediaPlayer实例,但下次点击按钮还是直接用这个已经失效的实例调用start(),自然就崩溃了
修复后的代码
我把代码重构了一下,核心思路是每次需要播放时,先检查MediaPlayer状态,如果已释放就重新创建新实例:
public class MainActivity extends AppCompatActivity { // 把MediaPlayer声明为类成员变量,方便跨方法访问 private MediaPlayer mp1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button bt1 = findViewById(R.id.b1); // 初始化第一个MediaPlayer实例 initMediaPlayer(); bt1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 检查实例是否为空或已失效,是就重新初始化 if (mp1 == null) { initMediaPlayer(); } // 确保MediaPlayer处于可播放状态再调用start if (!mp1.isPlaying()) { mp1.start(); } } }); } // 封装MediaPlayer的初始化逻辑,复用性更强 private void initMediaPlayer() { // 先释放之前的旧实例,避免内存泄漏 if (mp1 != null) { mp1.release(); } // 创建全新的MediaPlayer实例 mp1 = MediaPlayer.create(this, R.raw.button1); // 只设置一次OnCompletionListener,不用每次点击都重复设置 mp1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // 播放完成后释放实例,并置空标记 mp.release(); mp1 = null; } }); } // 别忘了在Activity销毁时释放MediaPlayer,防止内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (mp1 != null) { mp1.release(); mp1 = null; } } }
关键改进点
- 成员变量存储MediaPlayer:方便在初始化、点击事件、生命周期方法中统一管理实例状态
- 封装初始化方法:把创建实例、设置监听的逻辑抽出来,避免重复代码,也确保每次初始化都是干净的新实例
- 播放前检查状态:点击按钮时先判断实例是否有效,无效就重新创建,避免调用已释放实例的方法
- 生命周期收尾:在
onDestroy中释放MediaPlayer,避免Activity销毁后还持有资源导致内存泄漏
内容的提问来源于stack exchange,提问作者Ebpvg
相关产品推荐
相关产品推荐

