如何使用 MediaPlayer 单例
How to use a MediaPlayer Singleton
我是 Android 开发的新手,正从一个简单的音板应用程序着手。我开始使用多个片段开发音板,直到我意识到我正在使用 MediaPlayer 的多个实例。这不好,因为我一次只想播放一种声音。
我意识到我必须使用 MediaPlayer Singleton 来解决我的问题。唯一的问题是我无法在线找到 MediaPlayer Singleton 的许多来源或示例。
这是我最初放入每个片段中每个 "onCreateView" 的内容:
public static class FragmentPage1 extends Fragment {
int selectedSoundId;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_page1, container, false);
final MediaPlayer player = new MediaPlayer();
final Resources res = getResources();
final int[] buttonIds = { R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5, R.id.btn6, R.id.btn7, R.id.btn8, R.id.btn9 };
final int[] soundIds = { R.raw.sound01, R.raw.sound02, R.raw.sound03, R.raw.sound04, R.raw.sound05, R.raw.sound06, R.raw.sound07, R.raw.sound08, R.raw.sound09 };
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < buttonIds.length; i++) {
if (v.getId() == buttonIds[i]) {
selectedSoundId = soundIds[i];
AssetFileDescriptor afd = res.openRawResourceFd(soundIds[i]);
player.reset();
try {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
player.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
player.start();
break;
}
}
}
};
for (int i = 0; i < buttonIds.length; i++) {
ImageButton soundButton = (ImageButton) rootView.findViewById(buttonIds[i]);
registerForContextMenu(soundButton);
soundButton.setOnClickListener(listener);
}
return rootView;
}
}
据我所知,我可能会将 onClickListener 放在每个片段中,并将 MediaPlayer Singleton 放在新的 Java class 中。不过我不知道该怎么做。
如何实现 MediaPlayer 单例以及如何在片段的 "onCreateView" 方法中调用它?
非常感谢示例!
看,Singleton是一种设计模式,它是通过将默认构造函数设置为private来实现的,那么你应该提供一个get方法来恢复你的对象实例。查看下面的示例:
public class Foo {
private MediaPlaye md;
private Foo () {
md = new MediaPlayer();
}
public MediaPlayer getMediaPlayer () {
if (md == null) {
new Foo();
}
return md;
}
}
在您的情况下,最好的办法是创建一个将封装所有 MediaPlayer 方法的服务 class。这样做是因为,通常,开发人员希望播放器继续播放,即使用户离开了它所绑定的 Activity。在要使用 MediaPlayer API 的每个片段中,您可以绑定服务并使用定义的接口。看看下面的class:
public class MusicPlayerService extends android.app.Service implements MediaPlayer.OnPreparedListener,
MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener,
ObserverSubject {
private static final int NOTIFY_ID = 1;
private List<MusicPlayerObserver> mObservers;
private MediaPlayer mMediaPlayer;
private final IBinder playerBind = new MusicBinder();;
private List<Track> mPlaylist;
private Integer mPosition;
private Boolean isRepeating;
private Boolean isShuffling;
private Boolean isPrepared;
private Boolean isPaused;
// Callback Methods______________________________________________
@Override
public void onCreate() {
...
}
@Override
public void onPrepared(MediaPlayer mp) {
...
}
@Override
public IBinder onBind(Intent intent) {
return playerBind;
}
@Override
public boolean onUnbind(Intent intent) {
mMediaPlayer.stop();
mMediaPlayer.release();
return false;
}
@Override
public void onDestroy() {
stopForeground(true);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
// UTIL METHODS__________________________________________________
private Long getCurrentTrackId() {
return mPlaylist.get(mPosition).getTrackId();
}
private Long getCurrentAlbumId() {
return mPlaylist.get(mPosition).getAlbumId();
}
// MEDIA PLAYER INTERFACE________________________________________
public void play() {
...
}
public void pause() {
...
}
public void resume() {
...
}
public void next() {
...
}
public void previous() {
...
}
public void seekTo(int pos) {
...
}
// SERVICE INTERFACE PROVIDER_____________________________________
/**
* Interface through the component bound to this service can interact with it
*/
public class MusicBinder extends Binder {
public MusicPlayerService getService() {
return MusicPlayerService.this;
}
}
}
我强烈建议您遵循这个创建 MusicPlayer 服务的策略。另外,我建议你看看另一个名为 Observer 的设计模式。通常,在音乐应用程序中,您希望根据 MP 状态更新几个 UI 元素。 Observer 非常适合这种情况。
希望我能帮上一点忙。
我是 Android 开发的新手,正从一个简单的音板应用程序着手。我开始使用多个片段开发音板,直到我意识到我正在使用 MediaPlayer 的多个实例。这不好,因为我一次只想播放一种声音。
我意识到我必须使用 MediaPlayer Singleton 来解决我的问题。唯一的问题是我无法在线找到 MediaPlayer Singleton 的许多来源或示例。
这是我最初放入每个片段中每个 "onCreateView" 的内容:
public static class FragmentPage1 extends Fragment {
int selectedSoundId;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_page1, container, false);
final MediaPlayer player = new MediaPlayer();
final Resources res = getResources();
final int[] buttonIds = { R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5, R.id.btn6, R.id.btn7, R.id.btn8, R.id.btn9 };
final int[] soundIds = { R.raw.sound01, R.raw.sound02, R.raw.sound03, R.raw.sound04, R.raw.sound05, R.raw.sound06, R.raw.sound07, R.raw.sound08, R.raw.sound09 };
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < buttonIds.length; i++) {
if (v.getId() == buttonIds[i]) {
selectedSoundId = soundIds[i];
AssetFileDescriptor afd = res.openRawResourceFd(soundIds[i]);
player.reset();
try {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
player.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
player.start();
break;
}
}
}
};
for (int i = 0; i < buttonIds.length; i++) {
ImageButton soundButton = (ImageButton) rootView.findViewById(buttonIds[i]);
registerForContextMenu(soundButton);
soundButton.setOnClickListener(listener);
}
return rootView;
}
}
据我所知,我可能会将 onClickListener 放在每个片段中,并将 MediaPlayer Singleton 放在新的 Java class 中。不过我不知道该怎么做。
如何实现 MediaPlayer 单例以及如何在片段的 "onCreateView" 方法中调用它?
非常感谢示例!
看,Singleton是一种设计模式,它是通过将默认构造函数设置为private来实现的,那么你应该提供一个get方法来恢复你的对象实例。查看下面的示例:
public class Foo {
private MediaPlaye md;
private Foo () {
md = new MediaPlayer();
}
public MediaPlayer getMediaPlayer () {
if (md == null) {
new Foo();
}
return md;
}
}
在您的情况下,最好的办法是创建一个将封装所有 MediaPlayer 方法的服务 class。这样做是因为,通常,开发人员希望播放器继续播放,即使用户离开了它所绑定的 Activity。在要使用 MediaPlayer API 的每个片段中,您可以绑定服务并使用定义的接口。看看下面的class:
public class MusicPlayerService extends android.app.Service implements MediaPlayer.OnPreparedListener,
MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener,
ObserverSubject {
private static final int NOTIFY_ID = 1;
private List<MusicPlayerObserver> mObservers;
private MediaPlayer mMediaPlayer;
private final IBinder playerBind = new MusicBinder();;
private List<Track> mPlaylist;
private Integer mPosition;
private Boolean isRepeating;
private Boolean isShuffling;
private Boolean isPrepared;
private Boolean isPaused;
// Callback Methods______________________________________________
@Override
public void onCreate() {
...
}
@Override
public void onPrepared(MediaPlayer mp) {
...
}
@Override
public IBinder onBind(Intent intent) {
return playerBind;
}
@Override
public boolean onUnbind(Intent intent) {
mMediaPlayer.stop();
mMediaPlayer.release();
return false;
}
@Override
public void onDestroy() {
stopForeground(true);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
// UTIL METHODS__________________________________________________
private Long getCurrentTrackId() {
return mPlaylist.get(mPosition).getTrackId();
}
private Long getCurrentAlbumId() {
return mPlaylist.get(mPosition).getAlbumId();
}
// MEDIA PLAYER INTERFACE________________________________________
public void play() {
...
}
public void pause() {
...
}
public void resume() {
...
}
public void next() {
...
}
public void previous() {
...
}
public void seekTo(int pos) {
...
}
// SERVICE INTERFACE PROVIDER_____________________________________
/**
* Interface through the component bound to this service can interact with it
*/
public class MusicBinder extends Binder {
public MusicPlayerService getService() {
return MusicPlayerService.this;
}
}
}
我强烈建议您遵循这个创建 MusicPlayer 服务的策略。另外,我建议你看看另一个名为 Observer 的设计模式。通常,在音乐应用程序中,您希望根据 MP 状态更新几个 UI 元素。 Observer 非常适合这种情况。
希望我能帮上一点忙。