Android MediaPlayer是多线程的吗? [英] Is Android MediaPlayer multithreaded?

查看:261
本文介绍了Android MediaPlayer是多线程的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们可以从后台线程创建和使用Android MediaPlayer吗?

Can we create and use Android MediaPlayer from a background thread?

我问是因为所有回调事件(例如 OnError OnPrepared OnVideoSizeChanged 等)都被触发很奇怪.UI线程,即使MediaPlayer是在后台线程中创建(并使用)的,也会发生这种情况.

I ask because it's strange that all callback events (like OnError, OnPrepared, OnVideoSizeChanged, etc..) are fired in the main UI thread and this happens even if the MediaPlayer was created (and used) inside a background thread.

推荐答案

您可以从后台线程创建并使用 MediaPlayer .但是要在后台线程上接收回调,该线程必须实现 Looper .如果线程没有 Looper ,则将在主(UI)线程上调用回调.

You can create and use MediaPlayer from background thread. But to receive callbacks on the background thread that thread must have Looper implemented. If thread does not have Looper callbacks will be called on the main (UI) thread.

从Android文档 MediaPlayer :

From Android documentation MediaPlayer:

回调

应用程序可能需要注册以获取信息和错误事件,以便获知一些内部状态更新和播放或流式传输过程中可能出现运行时错误.注册这些事件是通过正确设置适当的侦听器来完成的(通过致电setOnPreparedListener(OnPreparedListener)setOnPreparedListener,setOnVideoSizeChangedListener(OnVideoSizeChangedListener)setOnVideoSizeChangedListener,setOnSeekCompleteListener(OnSeekCompleteListener)setOnSeekCompleteListener,setOnCompletionListener(OnCompletionListener)setOnCompletionListener,setOnBufferingUpdateListener(OnBufferingUpdateListener)setOnBufferingUpdateListener,setOnInfoListener(OnInfoListener)setOnInfoListener,setOnErrorListener(OnErrorListener)setOnErrorListener等).

Applications may want to register for informational and error events in order to be informed of some internal state update and possible runtime errors during playback or streaming. Registration for these events is done by properly setting the appropriate listeners (via calls to setOnPreparedListener(OnPreparedListener)setOnPreparedListener, setOnVideoSizeChangedListener(OnVideoSizeChangedListener)setOnVideoSizeChangedListener, setOnSeekCompleteListener(OnSeekCompleteListener)setOnSeekCompleteListener, setOnCompletionListener(OnCompletionListener)setOnCompletionListener, setOnBufferingUpdateListener(OnBufferingUpdateListener)setOnBufferingUpdateListener, setOnInfoListener(OnInfoListener)setOnInfoListener, setOnErrorListener(OnErrorListener)setOnErrorListener, etc).

按顺序接收与这些侦听器相关的各自的回调,需要应用程序才能在线程上创建MediaPlayer对象并运行自己的 Looper (默认情况下,主UI线程具有Looper正在运行).

In order to receive the respective callback associated with these listeners, applications are required to create MediaPlayer objects on a thread with its own Looper running (main UI thread by default has a Looper running).


最基本的示例,以观察在有或没有 Lopper 的线程上创建 MediaPlayer 之间的区别:


Most basic example to observe difference between creating MediaPlayer on threads with or without Lopper:

        HandlerThread thread = new HandlerThread("mp") {
//        Thread thread = new Thread() {

        @Override
        public void onLooperPrepared() {
//        public void run() {
            Log.d("XAPP", "BG Thread " + Long.toString(Thread.currentThread().getId()));
            MediaPlayer player = MediaPlayer.create(MainActivity.this, R.raw.sound);
            player.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
            {
                @Override
                public void onPrepared(MediaPlayer mp)
                {
                    Log.d("XAPP", "onPrepared " + Long.toString(Thread.currentThread().getId()));
                    mp.start();
                }
            });

            player.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
            {
                @Override
                public void onCompletion(MediaPlayer mp)
                {
                    Log.d("XAPP", "onCompletion " + Long.toString(Thread.currentThread().getId()));
                }
            });

        }};

        thread.start();

HandlerThread 具有 Looper ,运行上面的代码将导致以下logcat输出.所有回调都在后台线程上执行

HandlerThread has a Looper and running the above code will result in following logcat output . all callbacks are executed on background thread

01-11 14:33:04.122 5099-5099/xxx D/XAPP: UI Thread 1
01-11 14:33:04.122 5099-5173/xxx D/XAPP: BG Thread 416
01-11 14:33:04.152 5099-5173/xxx D/XAPP: onPrepared 416
01-11 14:33:05.133 5099-5173/xxx D/XAPP: onCompletion 416

切换到 Thread 实现(取消注释 Thread()行和 run()行,并注释 HandlerThread() Looper 的code>和 onLooperPrepared()行)将产生以下logcat,其中在主线程的上下文中执行回调

Switching to Thread implementation (uncomment Thread() line and run() line, and comment HandlerThread() and onLooperPrepared() lines) that does not have Looper will yield following logcat where callbacks are executed in the context of main thread

01-11 14:31:45.706 4916-4916/xxx D/XAPP: UI Thread 1
01-11 14:31:45.706 4916-4994/xxx D/XAPP: BG Thread 413
01-11 14:31:45.736 4916-4916/xxx D/XAPP: onPrepared 1
01-11 14:31:46.717 4916-4916/xxx D/XAPP: onCompletion 1

这篇关于Android MediaPlayer是多线程的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆