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

设置MediaPlayer的OnCompletionListener后,如何复用按钮播放音频?

解决MediaPlayer释放后重新播放崩溃的问题

嘿,这个问题我太熟了!你现在遇到的崩溃,核心原因是MediaPlayer调用release()后,原来的实例就彻底失效了,不能再复用它调用start()。咱们来一步步修复你的代码:

问题分析

你当前的代码有两个关键问题:

  1. 每次点击按钮都重复设置OnCompletionListener,这没必要而且可能引发意外
  2. 播放完成后调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:21:59