【问题标题】:How to use a MediaPlayer Singleton如何使用 MediaPlayer 单例
【发布时间】:2015-06-09 21:41:49
【问题描述】:

我是 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 类中。不过我不知道从那里做什么。

如何实现 MediaPlayer Singleton 以及如何在片段的“onCreateView”方法中调用它?

非常感谢您的示例!

【问题讨论】:

    标签: java android android-fragments media-player android-mediaplayer


    【解决方案1】:

    看,Singleton 是一种设计模式,它是通过将默认构造函数设置为私有来实现的,那么您应该提供一个 get 方法,您可以从中恢复您的对象实例。看看下面的例子:

    public class Foo {
        private MediaPlaye md;
    
        private Foo () {
            md = new MediaPlayer();
        }
    
        public MediaPlayer getMediaPlayer () {
            if (md == null) {
                new Foo();
            }
            return md;
        }
    }
    

    在您的情况下,最好的办法是创建一个 Service 类来封装所有 MediaPlayer 方法。这样做是因为通常开发人员希望玩家继续玩游戏,即使用户离开了它所绑定的 Activity。在每个要使用 MediaPlayer API 的 Fragment 中,您可以绑定 Service 并使用定义的接口。看看下面的课程:

    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 元素。观察者非常适合这种情况。

    希望我能帮上一点忙。

    【讨论】:

    • 您可以建议任何参考 github repo 吗?
    猜你喜欢
    • 1970-01-01
    • 2012-05-22
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 1970-01-01
    相关资源
    最近更新 更多