Android один экземпляр MediaPlayer — синглтон

Я собираюсь создать простое приложение для Android для воспроизведения звука при нажатии кнопки, но я борюсь с пониманием шаблона проектирования singleton, который был бы очень полезен в этом приложении. Чего я пытаюсь добиться, так это иметь несколько действий и совместно использовать только один экземпляр MediaPlayer среди них, чтобы когда пользователь нажимал кнопку, проигрывался звук, и если он нажимал ту же или другую кнопку в том же или другом действии, звук останавливался.

Вот мой код, но после двойного нажатия кнопки создается другой экземпляр MediaPlayer, и вы можете здесь воспроизводить один и тот же звук одновременно

public class MyMediaPlayer {
MediaPlayer mp;
private static volatile MyMediaPlayer instance = null;
private MyMediaPlayer() { }

public static MyMediaPlayer getInstance() {
    if (instance == null) {
        synchronized (MyMediaPlayer.class) {
            if (instance == null) {
                instance = new MyMediaPlayer();
            }
        }
    }

    return instance;
}
}

и MainActivity.java:

public class MainActivity extends Activity {

private MyMediaPlayer player = getInstance();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

}

public void playSound(View view){
    player.mp = MediaPlayer.create(getApplicationContext(), R.raw.sound);
    player.mp.start();
}
}

Поскольку я не очень опытен, не могли бы вы в дополнение к советам по приведенному выше коду объяснить мне, как я могу получить доступ к полю синглтона. Я не уверен, что мой подход правильный. Если у меня есть одноэлементный класс, и я хочу использовать этот экземпляр MediaPlayer, как мне это сделать?

Спасибо!


person Lenny    schedule 07.02.2015    source источник


Ответы (2)


Добавьте null проверку для mp объекта, который вы создаете при нажатии кнопки playSound:

public void playSound(View view){
    if(player.mp==null)
      player.mp = MediaPlayer.create(getApplicationContext(), R.raw.sound);
      player.mp.start();
}

потому что вы создали одноэлементный класс для класса MyMediaPlayer, который позволяет избежать создания нового объекта, когда player уже доступен. но mp инициализируется каждый раз.

РЕДАКТИРОВАТЬ: для воспроизведения нескольких звуков с использованием одного MediaPlayer сделайте это следующим образом:

if(player.mp ==null)
  player.mp = new MediaPlayer();
else
  player.mp.reset();
String fileName="android.resource://"+getPackageName()+
                                               "/"+ R.raw.sound;
player.mp.setDataSource(getApplicationContext(),Uri.parse(fileName));
player.mp.prepare();
player.mp.start();
person ρяσѕρєя K    schedule 07.02.2015
comment
Спасибо за ваш ответ! Думаю, я понял, как правильно получить доступ к одному объекту MediaPlayer! Это оператор if if(player.mp==null) - могу ли я использовать это, даже если я не буду создавать одноэлементный класс? - person Lenny; 07.02.2015
comment
@Lenny: Нет, потому что, если вы используете player.mp в нескольких классах, ваша текущая реализация в порядке. - person ρяσѕρєя K; 07.02.2015
comment
Ваше решение будет воспроизводить звук только один раз? После того, как я запускаю звуковой player.mp, создается, и оператор if больше не будет выполняться - person Lenny; 07.02.2015
comment
@Lenny: дай мне знать, чего ты хочешь? и мой текущий ответ соответствует вашему вопросу, который избегает использования нескольких объектов MediaPlayer - person ρяσѕρєя K; 07.02.2015
comment
извините, если мой вопрос был не ясен. Я хочу использовать один объект MediaPlayer для воспроизведения нескольких звуков. Пользователю будет представлено множество кнопок - каждая из этих кнопок позволит ему воспроизводить звук, но если звук от другой кнопки уже воспроизводится, нажатие новой кнопки остановит предыдущий звук и воспроизведет новый. - person Lenny; 07.02.2015
comment
@Lenny: см. мой ответ на редактирование. теперь приложение будет воспроизводить весь звук, используя один объект MediaPlayer - person ρяσѕρєя K; 07.02.2015
comment
Работает как шарм! Большое спасибо! Кроме того, я думаю, что с небольшой настройкой я мог бы использовать String fileName="android.resource://"+getPackageName()+ "/"+ R.raw.sound; player.mp.setDataSource(getApplicationContext(),Uri.parse(fileName)); для динамического назначения того, какой звук должен воспроизводиться при нажатии кнопки, верно? - person Lenny; 07.02.2015

person    schedule
comment
Спасибо за ответ. Я попробовал ваш код, но моя IDE говорит, что нет метода create(getApplicationContext(), R.raw.sound).start(), который есть, поскольку я уже его использую! Почему это? - person Lenny; 07.02.2015
comment
Вместо getApplicationContext() используйте MainActivity.this - person Harsh Parikh; 07.02.2015
comment
Еще одна вещь: как я могу использовать один метод для запуска () и остановки () воспроизведения моего звука с помощью одной кнопки? - person Lenny; 07.02.2015
comment
if(MyMediaPlayer.getInstance().isPlaying()) MyMediaPlayer.getInstance().stop(); еще MyMediaPlayer.getInstance().start(); - person Harsh Parikh; 07.02.2015