2016-06-27 4 views
3

Я реализую музыкальное приложение от this tutorial.Как работать с MediaPlayer и BaseAdapter

Существует класс BaseAdapter, используемый для отображения списка дорожек, и класс MusicPlayer для воспроизведения музыки. Оба являются переменными моего основного класса активности.

public class MainActivity extends Activity implements MediaPlayerControl{ 
     private MediaPlayer musicSrv; 
     private BaseAdapter songAdt; 
     ... 

MusicPlayer воспроизводит следующие треки, когда текущая отделка. Каков наилучший способ отправить сообщение в BaseAdapter для изменения отображения на каждой новой воспроизводимой дорожке (например, изменение цвета текущей дорожки)?

EDIT

Согласно комментариям, кажется, что использование интерфейса хорошего быть хорошим вариантом. Может ли кто-нибудь написать подробный ответ, объясняющий, как это сделать? Благодарю.

ответ

1

Благодаря комментариям, мне удалось реализовать решение с интерфейсом.

Это мой Основной класс активности, что освежить BaseAdapater каждый раз, когда песня изменилась:

public class MainActivity extends Activity implements MusicService.SongChangedListener { 
     private MediaPlayer musicSrv; 
     private BaseAdapter songAdt; 
     ... 

     @Override 
     public void songChanged(Song currentSong){ 
      songAdt.notifyDataSetChanged(); // refresh view 
     } 

И мой MusicService класс:

public class MusicService extends Service implements MediaPlayer.OnPreparedListener{ 
... 
private MainActivity activity; 
... 

public void setActivity(MainActivity act){ 
    //set the activity 
    activity = act; 
} 

public interface SongChangedListener { 
    void songChanged(Song song); 
} 
... 
public void playSong(){ 
     // this function is called each time a new song is played 
     activity.songChanged(playSong); 
     ... 
} 
0

Метод BaseAdapter, метод getView() предоставит вам представление, и вы должны изменить цвет вашей текущей дорожки, установив переменную в свой список и сбросив этот цвет по умолчанию, если переменная не установлена.

if (is this the current playing track) { 
    // Set the color of the view. 
} else { 
    // Set the color to default. 
} 

Если вы реализовали эту логику в настоящее время, то при смене текущего трека, а также переменную в списке, который отслеживает текущее воспроизведение медиа, простой songAdt.notifyDataSetChanged() попросит BaseAdapter к снова вызываться и будет устанавливать представление в соответствии с новыми данными. Для более глубокого понимания ListView вы можете обратиться this talk. Это поможет.

Желательно рассмотреть возможность обучения самостоятельно с помощью RecyclerView, его настоящего. ListView был ужасным прошлым.

public class Activity implements SongChangedListener { 
... 
    @Override 
    onCreate() { 
     .... 
     PlayerManager pManager = new PlayerManager(); 
    } 

    onResume() { 
     pManager.setListener(this); 
    } 

    onPause() { 
     pManager.setListener(null); 
    } 

    @Override 
    void songChanged (MediaId idOfSong) { 
     if (getActivity == null) //If you received a callback after activity was killed. 
      return; 
     // Change the current song as not playing in List. (for your adapter) 
     // Change the idOfSong to currently playing in List (for your adapter). 
     // change currentSong = idOfSong; 
     // notify that the data in List has changed (songAdt.notifyDataSetChanged) 
    } 

} 

И в вашем PlayerManager, вы можете создать интерфейс, или, возможно, индивидуальный класс для интерфейса, не имеет значения, как вы посылаете экземпляр интерфейса.

public class PlayerManager { 
    ... 
    private SongChangedListener mListener; 
    ... 

    public PlayerManager() { 
    } 

    public void setListener(SongChangedListener listener) { 
     mListener = listener; 
    } 

    public interface SongChangedListener { 
     void songChanged(MediaId idOfSong); 
    } 

    ... 
    public void playSong() { 
     ... 
     if (mListener != null) 
      mListener.songChanged(idOfNextSong); 
     ... 
    } 

В своем ответе вы передаете свою деятельность в свои службы, что во многих отношениях кажется неправильным. Если вы хотите реализовать связь между деятельностью и сервисом, есть много других способов сделать это. Обычно я использую Messenger в сочетании с обработчиком. Я бы предоставил более подробную информацию, но было бы более полезно, если бы вы исследовали его в документации и в других ответах. Его легко реализовать, как только вы поймете, как работают Messenger.

Кроме того, если вы ищете полнофункциональное приложение MediaPlayer, для вашей реализации потребуется намного больше кода котла. Также вам придется обрабатывать клики MediaButton (если кто-то нажал на воспроизведение/паузу на своих наушниках bluetooth или на их часах). Предпочтительно MediaSessionCompat является лучшей реализацией. Вы также можете ссылаться на следующий открытый MediaPlayer с открытым исходным кодом, который прекрасно реализует все минимально необходимые функции android-UniversalMusicPlayer.

+0

У меня songAdt.notifyDataSetChanged() в моем основном классе деятельности. Я использую его, когда меняю песни вручную. Проблема возникает, когда MediaPlayer автоматически переходит к следующей песне после завершения. Я не могу назвать songAdt.notifyDataSetChanged() в классе MediaPlayer, поскольку songAdt неизвестен. – PatriceG

+1

Попробуйте добавить обратные вызовы, создайте интерфейс в классе медиаплеера ur и получите метод с именем songChanged(). Внесите этот интерфейс в ur mainActivity, и когда вы смените песню в классе MediaPlayer, вызовите этот метод, чтобы изменение песни отражалось в ur mainActivity. Это довольно распространенный дизайн, используемый с обратными вызовами, чтобы уведомлять активность об изменениях. – Roadblock

+1

U должен будет передать экземпляр ur mainActivity для класса MediaPlayer (использовать конструктор MediaPlayers). Используйте этот экземпляр, чтобы вызвать метод songChanged. – Roadblock

0

Поддержание одной переменной в классе вашей музыкальной дорожки, которая указывает, находится ли эта песня в режиме воспроизведения или нет.

Проверьте это значение в своем getView() и сделайте кодировку в соответствии с ним.

if(model.is_playing) 
    //change your code for playing song 
else 
    //rest songs which are not playing 

Теперь, когда вы меняете песни Мануалов или автоматически, изменить это значение is_playing, сняты с охраной его от предыдущего трека и установите его в настоящее время играет трек.

+0

Да, но базовый адаптер должен быть обновлен, не так ли? Как это сделать? – PatriceG

+0

Вы можете использовать 'notifyDatasetChanged()' после обновления вашего списка. –

+0

. Моя проблема в том, что BaseAdapter не известен в классе MusicPlayer, где песни меняются. – PatriceG

0

Вам не нужно реализовывать свой собственный интерфейс обратного вызова. У медиаплеера уже есть oncompletionlistener, когда звук воспроизведения прекращается. Так что вам просто нужно обновить адаптер в методе oncompletion

public class MainActivity extends Activity implements MediaPlayerControl, MediaPlayer.OnCompletionListener{ 
    private MediaPlayer musicSrv; 
    private BaseAdapter songAdt; 


    @Override 
    public void onCreate() { 
     musicSrv.setOnCompletionListener(this); 
    } 

    @Override 
    public void onCompletion(MediaPlayer musicPlayer) { 
     songAdt.notifyDataSetChanged(); 
    } 
} 
+0

Пожалуйста, добавьте некоторое объяснение на ваш пост, что вы пытаетесь показать и почему и т. д. – Mfusiki

+0

Я добавил объяснение. –