我有一个带有片段的应用程序(Tab1.java,Tab2.java等),并使用ViewPager显示每个片段。 每个片段都有一个带有自定义适配器的recyclerview。
现在,当我转到显示所有艺术家列表的第三个片段时,问题就开始了;当我单击某个艺术家时,我开始了另一项活动。
在该活动中,我有此代码;
public class ListSongsActivity extends AppCompatActivity {
//Broadcast Intent Filter
public static final String broadCast_PlAY_NEW_SONG = "com.vince_mp3player.PlayNewSong";
//RecyclerView displays a scrolling list of elements based on large data sets
private RecyclerView recyclerViewListSongs;
//Custom RecyclerView Adapter.
private AllSongsAdapter allSongsAdapter;
private Toolbar mToolbar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_songs_layout);
//Holds all the songs in a scrollable list.
recyclerViewListSongs = findViewById(R.id.recyclerViewListSongs);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
// Connects the song list to an adapter
// (thing that creates several Layouts from the song list)
if ((Main.musicList != null) && (! Main.musicList.isEmpty())) {
allSongsAdapter = new AllSongsAdapter(this, Main.musicList);
recyclerViewListSongs.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerViewListSongs.setHasFixedSize(true);
recyclerViewListSongs.setAdapter(allSongsAdapter);
}
mToolbar = findViewById(R.id.mToolbar);
setSupportActionBar(mToolbar);
if ((getSupportActionBar() != null) && (bundle != null)) {
getSupportActionBar().setTitle((String)bundle.get("title"));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_home_up);
}
recyclerViewListSongs.addOnItemTouchListener(new OnItemClickListeners(getApplicationContext(), new OnItemClickListeners.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
playAudio(position);
Toast.makeText(getApplicationContext(), "You Clicked position: " + position + Main.musicList.get(position).getData(), Toast.LENGTH_SHORT).show();
}
}));
}
private void playAudio(int songIndex) {
//Check if service is active
if (!MediaPlayerService.musicBound) {
StorageUtil storageUtil = new StorageUtil(this);
storageUtil.storeSong(Main.musicList);
storageUtil.storeSongIndex(songIndex);
Intent playerIntent = new Intent(this, MediaPlayerService.class);
startService(playerIntent);
bindService(playerIntent, Main.musicConnection, Context.BIND_AUTO_CREATE);
} else {
//Store new songIndex in mSharedPreferences
StorageUtil storageUtil = new StorageUtil(this);
storageUtil.storeSongIndex(songIndex);
//Service is active
//Send media with BroadcastReceiver
Intent broadCastReceiverIntent = new Intent(broadCast_PlAY_NEW_SONG);
sendBroadcast(broadCastReceiverIntent);
}
}
}
问题是当我去参加此活动然后与所有歌手一起回到片段时,单击另一位歌手并选择一首歌曲,它仍会播放前一首歌曲。 如何重置我的recyclerview / adapter数据,以便保存我选择的新歌曲?
这是一个片段,其中显示了所有艺术家的列表,当单击某个项目时,便会启动您可以在顶部看到的活动
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_tab3, container, false);
recyclerViewArtists = rootView.findViewById(R.id.recyclerViewArtists);
initRecyclerView();
return rootView;
}
private void initRecyclerView(){
items = Main.songs.getArtists();
if ((items != null) && (! items.isEmpty())) {
Adapter adapter = new Adapter(getContext(), items);
recyclerViewArtists.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerViewArtists.setHasFixedSize(true);
recyclerViewArtists.setAdapter(adapter);
Log.i(TAG, "Artists found in list!");
recyclerViewArtists.addOnItemTouchListener(new OnItemClickListeners(getContext(), new OnItemClickListeners.OnItemClickListener() {
@TargetApi(Build.VERSION_CODES.O)
@Override
public void onItemClick(View view, int position) {
Toast.makeText(getContext(), "You Clicked position: " + position + " " + items.get(position) , Toast.LENGTH_SHORT).show();
if (! Main.songs.isInitialized()){
return;
}
String selectedArtist = items.get(position);
Main.musicList = Main.songs.getSongsByArtist(selectedArtist);
Intent intent = new Intent(getContext(), ListSongsActivity.class);
intent.putExtra("title", selectedArtist);
startActivity(intent);
}
}));
}else{
Log.i(TAG, "No artists found in list!");
}
}
服务等级
public class MediaPlayerService extends Service implements MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener,
MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener, AudioManager.OnAudioFocusChangeListener, MediaPlayer.OnCompletionListener {
public static final String mACTION_PLAY = "com.vince_mp3player.mACTION_PLAY";
public static final String mACTION_PAUSE = "com.vince_mp3player.mACTION_PAUSE";
public static final String mACTION_PREVIOUS = "com.vince_mp3player.mACTION_PREVIOUS";
public static final String mACTION_NEXT = "com.vince_mp3player.mACTION_NEXT";
public static final String mACTION_STOP = "com.vince_mp3player.mACTION_STOP";
public static final String broadCast_UPDATE_SONG = "com.vince_mp3player.broadCast_UPDATE_SONG";
public static MediaPlayer mediaPlayer = new MediaPlayer();
public static boolean isPlaying;
private final String TAG = this.getClass().getName();
//Media Session
private MediaSessionManager mMediaSessionManager;
private MediaSessionCompat mMediaSessionCompat;
private MediaControllerCompat.TransportControls mTransportControls;
//Notification ID
private static final int NOTIFICATION_ID = 101;
private AudioManager mAudioManager;
private PhoneStateListener mPhoneStateListener;
private boolean incomingCall = false;
private TelephonyManager mTelephonyManager;
private int resumePos;
private int songIndex = -1;
private ArrayList<Song> songList;
private Song activeSong;
@Override
public void onCreate() {
super.onCreate();
callStateListener();
registerNoisyBroadcastReceiver();
registerNewSongBroadCastReceiver();
}
/**
* Tells if this service is bound to an Activity.
*/
public static boolean musicBound = false;
/**
* Defines the interaction between an Activity and this Service.
*/
public class MusicBinder extends Binder {
public MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
/**
* Token for the interaction between an Activity and this Service.
*/
private final IBinder mBinder = new MusicBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
return false;
}
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange){
case AudioManager.AUDIOFOCUS_GAIN:
if (mediaPlayer == null) initMediaPlayer();
else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
private boolean requestAudioFocus() {
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
return true;
}
return false;
}
private boolean removeAudioFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
mAudioManager.abandonAudioFocus(this);
}
private BroadcastReceiver NoisyBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
pauseSong();
NotificationBuilder(PlaybackStatus.PAUSED);
}
};
private BroadcastReceiver NewSongBroadCastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
songIndex = new StorageUtil(getApplicationContext()).loadSongIndex();
if (songIndex != -1 && songIndex < songList.size()){
activeSong = songList.get(songIndex);
}else{
stopSelf();
}
stopSong();
mediaPlayer.reset();
initMediaPlayer();
updateMetaData();
NotificationBuilder(PlaybackStatus.PLAYING);
}
};
private void registerNoisyBroadcastReceiver(){
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(NoisyBroadcastReceiver, intentFilter);
}
private void registerNewSongBroadCastReceiver(){
IntentFilter intentFilter = new IntentFilter(Tab1.broadCast_PlAY_NEW_SONG);
registerReceiver(NewSongBroadCastReceiver, intentFilter);
}
private void callStateListener(){
mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mPhoneStateListener = new PhoneStateListener(){
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
if (mediaPlayer != null){
pauseSong();
}
break;
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer != null) {
pauseSong();
incomingCall = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (mediaPlayer != null) {
if (incomingCall) {
incomingCall = false;
playSong();
}
}
break;
}
super.onCallStateChanged(state, incomingNumber);
}
};
if (mTelephonyManager != null){
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//Load data from SharedPreferences
StorageUtil storage = new StorageUtil(getApplicationContext());
songList = storage.getSongs();
songIndex = storage.loadSongIndex();
if (songIndex != -1 && songIndex < songList.size()) {
//index is in a valid range
activeSong = songList.get(songIndex);
} else {
stopSelf();
}
} catch (NullPointerException e) {
stopSelf();
Log.e(TAG, e.getMessage());
}
//Request audio focus
if (!requestAudioFocus()) {
//Could not gain focus
stopSelf();
}
if (mMediaSessionManager == null) {
try {
initMediaSession();
initMediaPlayer();
} catch (RemoteException e) {
e.printStackTrace();
stopSelf();
}
NotificationBuilder(PlaybackStatus.PLAYING);
}
//Handle Intent action from MediaSession.TransportControls
handleIncomingActions(intent);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
switch (what){
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
Log.d("Mediaplayer Error", "MEDIA ERROR NOT VALID FOR PROGRESSIVE PLAYBACK" + extra);
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.d("Mediaplayer Error" , "MEDIA ERROR SERVER DIED" + extra);
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.d("Mediaplayer Error", "MEDIA ERROR UNKNOWN" + extra);
}
return false;
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
return false;
}
@Override
public void onPrepared(MediaPlayer mp) {
playSong();
}
@Override
public void onSeekComplete(MediaPlayer mp) {
}
@Override
public void onCompletion(MediaPlayer mp) {
stopSong();
stopSelf();
}
private void initMediaPlayer() {
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(activeSong.getData());
} catch (Exception e) {
Log.e(TAG, "ERROR SETTING DATA SOURCE", e);
stopSelf();
}
mediaPlayer.prepareAsync();
}
private void initMediaSession() throws RemoteException{
if (mMediaSessionManager != null) return;
mMediaSessionManager = (MediaSessionManager)getSystemService(Context.MEDIA_SESSION_SERVICE);
//new MediaSession
mMediaSessionCompat = new MediaSessionCompat(getApplicationContext(), "AudioPlayer");
//Transport controls
mTransportControls = mMediaSessionCompat.getController().getTransportControls();
//set MediaSession
mMediaSessionCompat.setActive(true);
//MediaSession handles transport controls
mMediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
//set MediaSession's MetaData
updateMetaData();
mMediaSessionCompat.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() {
super.onPlay();
resumeSong();
NotificationBuilder(PlaybackStatus.PLAYING);
}
@Override
public void onPause() {
super.onPause();
pauseSong();
NotificationBuilder(PlaybackStatus.PAUSED);
}
@Override
public void onSkipToNext() {
super.onSkipToNext();
nextSong();
updateMetaData();
NotificationBuilder(PlaybackStatus.PLAYING);
}
@Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
previousSong();
updateMetaData();
NotificationBuilder(PlaybackStatus.PLAYING);
}
@Override
public void onStop() {
super.onStop();
removeNotification();
stopSelf();
}
@Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
}
});
}
private void updateMetaData(){
mMediaSessionCompat.setMetadata(new MediaMetadataCompat.Builder().putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, null)
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ARTIST, activeSong.getArtist()).putString(MediaMetadataCompat.METADATA_KEY_ALBUM, activeSong.getAlbum())
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, activeSong.getTitle()).build());
}
private void NotificationBuilder(PlaybackStatus playbackStatus){
int notificationAction = R.drawable.ic_action_pause_white;
PendingIntent play_pause_action = null;
if (playbackStatus == PlaybackStatus.PLAYING){
//Pause button created when song is PLAYING
notificationAction = R.drawable.ic_action_pause_white;
play_pause_action = playbackAction(1);
isPlaying = true;
//Send broadcast update song info
Intent broadCastReceiverIntent = new Intent(broadCast_UPDATE_SONG);
sendBroadcast(broadCastReceiverIntent);
}else if (playbackStatus == PlaybackStatus.PAUSED){
//Play button created when song is PAUSED
notificationAction = R.drawable.ic_action_play;
play_pause_action = playbackAction(0);
isPlaying = false;
//Send broadcast update song info
Intent broadCastReceiverIntent = new Intent(broadCast_UPDATE_SONG);
sendBroadcast(broadCastReceiverIntent);
}
//Create notification
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this).setShowWhen(false)
.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle().setMediaSession(mMediaSessionCompat.getSessionToken()).setShowActionsInCompactView(0, 1 ,2))
.setSmallIcon(android.R.drawable.stat_sys_headset).setContentTitle(activeSong.getTitle()).setContentText(activeSong.getArtist())
.addAction(R.drawable.ic_action_prev_white, "previous", playbackAction(3))
.addAction(notificationAction, "pause", play_pause_action).addAction(R.drawable.ic_action_next_white, "next", playbackAction(2))
.setColor(getResources().getColor(R.color.theme1));
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, songList.get(songIndex).getAlbumID());
//Load album art in notification
try
{
Bitmap largeIcon = MediaStore.Images.Media.getBitmap(getContentResolver() , albumArtUri);
notificationBuilder.setLargeIcon(largeIcon);
}
catch (Exception e)
{
//handle exception
e.printStackTrace();
}
((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notificationBuilder.build());
}
private PendingIntent playbackAction(int actionNumber) {
Intent playbackAction = new Intent(this, MediaPlayerService.class);
switch (actionNumber) {
case 0:
// Play
playbackAction.setAction(mACTION_PLAY);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
case 1:
// Pause
playbackAction.setAction(mACTION_PAUSE);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
case 2:
// Next track
playbackAction.setAction(mACTION_NEXT);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
case 3:
// Previous track
playbackAction.setAction(mACTION_PREVIOUS);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
default:
break;
}
return null;
}
private void handleIncomingActions(Intent playbackAction) {
if (playbackAction == null || playbackAction.getAction() == null) return;
String actionString = playbackAction.getAction();
if (actionString.equalsIgnoreCase(mACTION_PLAY)) {
mTransportControls.play();
} else if (actionString.equalsIgnoreCase(mACTION_PAUSE)) {
mTransportControls.pause();
} else if (actionString.equalsIgnoreCase(mACTION_NEXT)) {
mTransportControls.skipToNext();
} else if (actionString.equalsIgnoreCase(mACTION_PREVIOUS)) {
mTransportControls.skipToPrevious();
} else if (actionString.equalsIgnoreCase(mACTION_STOP)) {
mTransportControls.stop();
}
}
private void removeNotification(){
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
private void playSong(){
if (!mediaPlayer.isPlaying()){
mediaPlayer.start();
}
}
private void nextSong(){
if (songIndex == songList.size() - 1) {
songIndex = 0;
activeSong = songList.get(songIndex);
}else{
++songIndex;
activeSong = songList.get(songIndex);
Toast.makeText(getApplicationContext(), "You Clicked position: " + songIndex + " " + songList.get(songIndex).getData(), Toast.LENGTH_SHORT).show();
}
new StorageUtil(getApplicationContext()).storeSongIndex(songIndex);
stopSong();
mediaPlayer.reset();
initMediaPlayer();
//Send broadcast update song info
Intent broadCastReceiverIntent = new Intent(broadCast_UPDATE_SONG);
sendBroadcast(broadCastReceiverIntent);
}
private void previousSong(){
if(songIndex == 0){
songIndex = songList.size() - 1;
activeSong = songList.get(songIndex);
}else{
--songIndex;
activeSong = songList.get(songIndex);
Toast.makeText(getApplicationContext(), "You Clicked position: " + songIndex + " " + songList.get(songIndex).getData(), Toast.LENGTH_SHORT).show();
}
new StorageUtil(getApplicationContext()).storeSongIndex(songIndex);
stopSong();
mediaPlayer.reset();
initMediaPlayer();
//Send broadcast update song info
Intent broadCastReceiverIntent = new Intent(broadCast_UPDATE_SONG);
sendBroadcast(broadCastReceiverIntent);
}
private void stopSong(){
if (mediaPlayer == null) return;
if (mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
}
private void pauseSong(){
if (mediaPlayer.isPlaying()){
mediaPlayer.pause();
resumePos = mediaPlayer.getCurrentPosition();
}
}
private void resumeSong(){
if (!mediaPlayer.isPlaying()){
mediaPlayer.seekTo(resumePos);
mediaPlayer.start();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
stopSong();
mediaPlayer.release();
}
removeAudioFocus();
if (mTelephonyManager != null){
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
}
removeNotification();
unregisterReceiver(NoisyBroadcastReceiver);
unregisterReceiver(NewSongBroadCastReceiver);
new StorageUtil(getApplicationContext()).clearCachedAudioPlaylist();
}
}
每次用户单击歌曲时,我都会使用playAudio方法检查服务是否处于活动状态,否则,我将启动服务时,将数组列表与歌曲和songIndex一起存储。 如果它处于活动状态,我将存储并发送广播以播放新歌曲。 此类存储songIndex和ArrayLists
public class StorageUtil {
private final String STORAGE = "com.vince_mp3player.STORAGE";
private SharedPreferences mSharedPreferences;
private Context context;
private SharedPreferences.Editor mEditor;
public StorageUtil(Context context){
this.context = context;
}
public void storeSong(List<Song> list){
mSharedPreferences = context.getSharedPreferences(STORAGE, Context.MODE_PRIVATE);
mEditor = mSharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(list);
mEditor.putString("songList", json);
mEditor.apply();
}
public ArrayList<Song> getSongs(){
mSharedPreferences = context.getSharedPreferences(STORAGE, Context.MODE_PRIVATE);
Gson gson = new Gson();
String json = mSharedPreferences.getString("songList", null);
Type type = new TypeToken<List<Song>>(){
}.getType();
return gson.fromJson(json, type);
}
public void storeSongIndex(int index) {
mSharedPreferences = context.getSharedPreferences(STORAGE, Context.MODE_PRIVATE);
mEditor = mSharedPreferences.edit();
mEditor.putInt("songIndex", index);
mEditor.apply();
}
public int loadSongIndex() {
mSharedPreferences = context.getSharedPreferences(STORAGE, Context.MODE_PRIVATE);
return mSharedPreferences.getInt("songIndex", -1);//return -1 if no data found
}
public void clearCachedAudioPlaylist() {
mSharedPreferences = context.getSharedPreferences(STORAGE, Context.MODE_PRIVATE);
mEditor = mSharedPreferences.edit();
mEditor.clear();
mEditor.apply();
}
}
Main.musicList
公共静态ArrayList musicList = null;
主要歌曲
静态静态SongList歌曲= new SongList();
SongList 类,用于从媒体存储区和返回数组列表的方法中获取所有歌曲信息。 例如:
/**
* Returns a list of Songs belonging to a specified artist.
*/
public ArrayList<Song> getSongsByArtist(String desiredArtist) {
ArrayList<Song> songsByArtist = new ArrayList<Song>();
for (Song song : songs) {
String currentArtist = song.getArtist();
if (currentArtist.equals(desiredArtist))
songsByArtist.add(song);
}
// Sorting resulting list by Album
Collections.sort(songsByArtist, new Comparator<Song>() {
public int compare(Song a, Song b)
{
return a.getAlbum().compareTo(b.getAlbum());
}
});
return songsByArtist;
}