Android MediaPlayer是多线程的吗? [英] Is Android MediaPlayer multithreaded?
问题描述
我们可以从后台线程创建和使用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屋!