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

如何从异步线程返回值?MediaPlayer迁移到Executor后返回报错如何解决

问题原因

  • 你使用Executor.execute()提交的是Runnable类型任务,该接口的run方法没有返回值,所以不能在内部直接return布尔值,才会触发Unexpected return value报错;同时主线程的playFile方法没有对应返回语句,自然触发Missing return statement报错。
  • 你用AtomicReference还是拿不到正确值的核心原因是:异步任务提交后主线程不会等待任务执行完成,直接读取了初始值false,此时异步任务还没完成变量赋值操作。

解决方案

方案1:用Callable+Future同步获取结果(会阻塞调用线程)

如果调用playFile的线程允许阻塞,可以用submit方法提交Callable类型任务,通过Future.get()阻塞等待任务执行完成拿到返回值:

public boolean playFile(String path) {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Callable<Boolean> playTask = () -> {
        MediaPlayer mp = new MediaPlayer();
        mp.setAudioAttributes(AudioFocusManager.getPlaybackAttributes());
        try {
            mp.setDataSource(path);
            mp.prepare();
            mp.start();
            mp.setOnErrorListener((mp1, what, extra) -> true);
            mp.setOnCompletionListener(mp1 -> {});
            return true;
        } catch (Exception e) {
            AudioFocusManager.releaseAudioFocus();
            return false;
        }
    };

    Future<Boolean> future = executor.submit(playTask);
    try {
        // 阻塞等待异步任务执行完成,拿到返回结果
        return future.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
        return false;
    } finally {
        // 如果是全局复用的线程池不要执行shutdown,根据业务调整
        executor.shutdown();
    }
}

注意:不要在主线程/UI线程使用该方案,否则会造成界面卡顿甚至ANR。


方案2:异步回调(不阻塞调用线程,推荐Android等UI场景使用)

如果不能阻塞调用线程,就不要让playFile同步返回结果,改成任务执行完成后通过回调返回结果:
首先自定义回调接口:

public interface PlayCallback {
    void onPlayResult(boolean isSuccess);
}

修改playFile方法:

public void playFile(String path, PlayCallback callback) {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.execute(() -> {
        boolean playResult = false;
        MediaPlayer mp = new MediaPlayer();
        mp.setAudioAttributes(AudioFocusManager.getPlaybackAttributes());
        try {
            mp.setDataSource(path);
            mp.prepare();
            mp.start();
            mp.setOnErrorListener((mp1, what, extra) -> true);
            mp.setOnCompletionListener(mp1 -> {});
            playResult = true;
        } catch (Exception e) {
            AudioFocusManager.releaseAudioFocus();
            playResult = false;
        } finally {
            // 如果需要回调在主线程执行,可以通过主线程Handler转发回调
            if (callback != null) {
                callback.onPlayResult(playResult);
            }
            executor.shutdown();
        }
    });
}

调用示例:

playFile("/sdcard/test.mp3", isSuccess -> {
    // 在这里处理播放结果逻辑
    if (isSuccess) {
        // 播放成功
    } else {
        // 播放失败
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:54:03