Нужно ли мне несколько медиаплееров для нескольких медиафайлов?

Я разрабатываю приложение музыкальной библиотеки с помощью JavaFX, и у меня возникают некоторые проблемы с тем, как я должен правильно использовать класс MediaPlayer.

Это мой текущий метод настройки и воспроизведения аудиофайлов:

private static MediaPlayer musicPlayer;

public static void setMedia(String path) {
    try {
        musicPlayer = new MediaPlayer(new Media(new File(path).toURI().toASCIIString()));
        musicPlayer.play();
    } catch (Exception e) {
        System.out.println("invald file");
        System.out.println(e.getMessage());
    }
}

Скажем, например, у меня есть два аудиофайла...

file1.mp3
file2.mp3

...И две кнопки, которые отправляют один из этих двух файлов вышеуказанным методом:

button1.setOnAction(event -> {
    setMedia("file1.mp3");
});

button2.setOnAction(event -> {
    setMedia("file2.mp3");
});

Обычно было бы разумно, чтобы оба аудиофайла воспроизводились друг над другом, потому что я создаю новый объект MediaPlayer каждый раз, когда я вызываю метод, однако этот объект является статическим. Может быть, я неправильно понимаю, как работают статические объекты, но разве это не должно означать, что может быть только один экземпляр этого объекта? И, в свою очередь, не будет ли это означать, что при каждом вызове метода setMedia медиафайл объекта MediaPlayer будет перезаписываться?

Я не нашел способа «установить» или «перезаписать» медиафайл для объекта MediaPlayer без создания его нового экземпляра. Похоже, у него нет способа сделать это. Это наводит меня на мысль, что у меня должен быть массив объектов MediaPlayer для каждого аудиофайла. Это правильно? Или я просто что-то пропустил здесь?


person A. Cucci    schedule 30.05.2017    source источник
comment
не должно ли это означать, что может быть только один экземпляр этого объекта. Нет. Это означает, что ваш класс имеет только одну ссылку на MediaPlayer.   -  person James_D    schedule 30.05.2017
comment
Спасибо за разъяснение, James_D. Я обязательно буду иметь это в виду.   -  person A. Cucci    schedule 30.05.2017
comment
На самом деле, мое утверждение в том комментарии не совсем верно. Это означает, что ссылка MediaPlayer является свойством класса, а не свойством экземпляров класса. (Таким образом, есть только одна ссылка MediaPlayer, даже если вы создаете множество экземпляров любого класса, в котором все это определено.)   -  person James_D    schedule 30.05.2017


Ответы (2)


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

Это верно. документация для конструктора MediaPlayer явно описывает это:

public MediaPlayer(Media media)

Создайте проигрыватель для определенного носителя. Это единственный способ связать объект Media с MediaPlayer: после создания проигрывателя его нельзя изменить.


Может быть, я неправильно понимаю, как работают статические объекты, но разве это не должно означать, что может быть только один экземпляр этого объекта?

Да, вы неверно истолковываете это.

Статическая ссылка на MediaPlayer просто означает, что ваш класс имеет только одну ссылку на MediaPlayer. (Обычно утверждается, что единственная ссылка MediaPlayer является общей для всех экземпляров вашего класса. Мне это не нравится: это как бы подразумевает, что у вас должен быть хотя бы один экземпляр вашего класса, что неверно. на самом деле это статика просто означает, что ссылка MediaPlayer является свойством класса, а не свойством экземпляров класса.) Простая замена ссылки (чтобы она ссылалась на другой MediaPlayer) не удаляла предыдущий объект из кучи . Он по-прежнему существует в памяти, по-прежнему имеет все свои свойства и т. д. В вашем классе просто больше нет ссылки на него.

В общем случае, если нет активной ссылки на объект, он подходит для сборки мусора. Однако в этом случае, если медиа воспроизводится, инструментарий FX будет поддерживать ссылку на него, чтобы он действительно физически воспроизводился. MediaPlayer определяет метод dispose для освобождения его базовых ресурсов. Таким образом, ваш метод, вероятно, должен выглядеть примерно так:

public static void setMedia(String path) {

    if (mediaPlayer != null) {
        mediaPlayer.stop();
        mediaPlayer.dispose();
    }
    try {
        musicPlayer = new MediaPlayer(new Media(new File(path).toURI().toASCIIString()));
        musicPlayer.play();
    } catch (Exception e) {
        System.out.println("invald file");
        System.out.println(e.getMessage());
    }
}

Почти наверняка нет никакой необходимости делать все static: это не делает ничего полезного для вас.

person James_D    schedule 30.05.2017
comment
Спасибо, я знал, что делаю что-то не так. На самом деле я пробовал ваш способ с методом dispose раньше, за исключением того, что я проверял, был ли вместо этого метод getMedia MediaPlayer нулевым. - person A. Cucci; 30.05.2017

Кажется, вы путаетесь между двумя понятиями: статические переменные и синглтоны. То, что вы сказали здесь there can only ever be one instance of this object, относится к синглтонам, но не к статическим переменным в целом. Для статических переменных это означает только то, что область действия переменной является глобальной. Другими словами, будет только одна ссылка на эти переменные.

Пример:

// This is just a general static variable
private static MediaPlayer mediaPlayer;
mediaPlayer = new MediaPlayer(...);
mediaPlayer = new MediaPlayer(...); // this second assignment is ok

// This is a singleton - note the key word `final`
private static final MediaPlayer mediaPlayer;
mediaPlayer = new MediaPlayer(...); // ok
mediaPlayer = new MediaPlayer(...); // compile error
person Dat Nguyen    schedule 30.05.2017
comment
Я так не думаю. Но давайте не будем вдаваться в эту червячную банку (и дискутировать, используя мнения) :) - person Dat Nguyen; 30.05.2017