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

Android中释放与停止MediaPlayer时出现ANR问题求助

排查PlayMusicFragment中onStop引发ANR的关键方向
  • 检查MediaPlayer回调的线程与锁竞争
    虽然采用prepareAsync()异步准备,但MediaPlayer的状态回调(如onPrepared()、onError())默认在主线程执行。如果回调中存在同步锁、耗时逻辑,会和onStop()里的stop()/release()操作产生锁竞争,阻塞主线程。需确认所有回调仅处理UI状态变更,无阻塞性操作。

  • 排查准备与释放的竞态条件
    当onStop()触发时,prepareAsync()的回调可能仍在主线程执行,此时调用stop()/release()会触发MediaPlayer内部同步锁等待。可通过原子变量标记状态,避免阻塞:

    private AtomicBoolean isPreparing = new AtomicBoolean(false);
    
    // 启动异步准备前标记
    isPreparing.set(true);
    mediaPlayer.prepareAsync();
    
    // onPrepared回调中更新状态
    @Override
    public void onPrepared(MediaPlayer mp) {
        isPreparing.set(false);
        // 处理播放按钮显示逻辑
    }
    
    // onStop中根据状态处理
    @Override
    public void onStop() {
        super.onStop();
        if (mediaPlayer != null) {
            if (isPreparing.get()) {
                mediaPlayer.reset(); // 避免等待准备完成
            } else {
                mediaPlayer.stop();
            }
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
    
  • 模拟极端网络场景复现
    本地测试未复现可能是网络环境稳定,prepareAsync()快速完成。可模拟弱网、网络中断场景,让MediaPlayer长时间处于准备状态,再触发Fragment的onStop(),验证是否出现ANR——此时MediaPlayer内部可能在等待网络回调,调用释放操作会阻塞主线程。

  • 分析Crashlytics的ANR调用栈
    Crashlytics的ANR报告包含主线程快照,重点查看onStop()执行时主线程阻塞的具体方法(如MediaPlayer.stop()或release()内部),这能直接定位是MediaPlayer内部锁等待,还是外部代码阻塞。

  • 检查MediaPlayer实例的生命周期管理
    若Fragment重建时未正确清理旧实例,会导致onStop()操作多个MediaPlayer实例,引发同步问题。需确保MediaPlayer为Fragment成员变量,在onStop()/onDestroyView()中彻底释放并置空,避免重复操作。

内容的提问来源于stack exchange,提问作者Nexussim Lements

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:22:08