diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java index eeb8bf5c..c66e8981 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java @@ -55,6 +55,8 @@ public class ArtistSongAdapter extends ArrayAdapter implements MaterialCab public void swapDataSet(ArrayList dataSet) { this.dataSet = dataSet; + clear(); + addAll(dataSet); notifyDataSetChanged(); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/model/Song.java b/app/src/main/java/com/kabouzeid/gramophone/model/Song.java index 47854670..9774efd3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/model/Song.java +++ b/app/src/main/java/com/kabouzeid/gramophone/model/Song.java @@ -94,7 +94,7 @@ public class Song implements Parcelable { ", year=" + year + ", duration=" + duration + ", data='" + data + '\'' + - ", getDateModified=" + dateModified + + ", dateModified=" + dateModified + ", albumId=" + albumId + ", albumName='" + albumName + '\'' + ", artistId=" + artistId + diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 162e3c51..ddc5c75b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -1,9 +1,12 @@ package com.kabouzeid.gramophone.ui.activities; +import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; @@ -32,6 +35,7 @@ import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.interfaces.PaletteColorHolder; import com.kabouzeid.gramophone.loader.AlbumLoader; import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks; +import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader; import com.kabouzeid.gramophone.model.Album; import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity; import com.kabouzeid.gramophone.ui.activities.tageditor.AbsTagEditorActivity; @@ -42,14 +46,16 @@ import com.kabouzeid.gramophone.util.Util; import butterknife.Bind; import butterknife.ButterKnife; +import hugo.weaving.DebugLog; /** * Be careful when changing things in this Activity! */ -public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements PaletteColorHolder, CabHolder { +public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements PaletteColorHolder, CabHolder, LoaderManager.LoaderCallbacks { public static final String TAG = AlbumDetailActivity.class.getSimpleName(); private static final int TAG_EDITOR_REQUEST = 2001; + private static final int LOADER_ID = 1; public static final String EXTRA_ALBUM_ID = "extra_album_id"; @@ -83,10 +89,11 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements supportPostponeEnterTransition(); - getAlbumFromIntentExtras(); setUpObservableListViewParams(); setUpToolBar(); setUpViews(); + + getSupportLoaderManager().initLoader(LOADER_ID, getIntent().getExtras(), this); } @Override @@ -120,15 +127,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements } }; - private void getAlbumFromIntentExtras() { - Bundle intentExtras = getIntent().getExtras(); - final int albumId = intentExtras.getInt(EXTRA_ALBUM_ID); - album = AlbumLoader.getAlbum(this, albumId); - if (album.songs.isEmpty()) { - finish(); - } - } - private void setUpObservableListViewParams() { albumArtViewHeight = getResources().getDimensionPixelSize(R.dimen.header_image_height); toolbarColor = DialogUtils.resolveColor(this, R.attr.defaultFooterColor); @@ -141,14 +139,12 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements } private void setUpViews() { - albumTitleView.setText(album.getTitle()); - setUpRecyclerViewView(); + setUpRecyclerView(); setUpSongsAdapter(); - loadAlbumCover(); } private void loadAlbumCover() { - SongGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong()) + SongGlideRequest.Builder.from(Glide.with(this), getAlbum().safeGetFirstSong()) .checkIgnoreMediaStore(this) .generatePalette(this).build() .dontAnimate() @@ -187,7 +183,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements return toolbarColor; } - private void setUpRecyclerViewView() { + private void setUpRecyclerView() { setUpRecyclerViewPadding(); recyclerView.setScrollViewCallbacks(observableScrollViewCallbacks); final View contentView = getWindow().getDecorView().findViewById(android.R.id.content); @@ -215,7 +211,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements } private void setUpSongsAdapter() { - adapter = new AlbumSongAdapter(this, album.songs, R.layout.item_list, false, this); + adapter = new AlbumSongAdapter(this, getAlbum().songs, R.layout.item_list, false, this); recyclerView.setLayoutManager(new GridLayoutManager(this, 1)); recyclerView.setAdapter(adapter); adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { @@ -227,11 +223,8 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements }); } - private void refresh() { - album = AlbumLoader.getAlbum(this, album.getId()); - albumTitleView.setText(album.getTitle()); - loadAlbumCover(); - adapter.swapDataSet(album.songs); + private void reload() { + getSupportLoaderManager().restartLoader(LOADER_ID, getIntent().getExtras(), this); } @Override @@ -258,11 +251,11 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements return true; case R.id.action_tag_editor: Intent intent = new Intent(this, AlbumTagEditorActivity.class); - intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.getId()); + intent.putExtra(AbsTagEditorActivity.EXTRA_ID, getAlbum().getId()); startActivityForResult(intent, TAG_EDITOR_REQUEST); return true; case R.id.action_go_to_artist: - NavigationUtil.goToArtist(this, album.getArtistId()); + NavigationUtil.goToArtist(this, getAlbum().getArtistId()); return true; } return super.onOptionsItemSelected(item); @@ -272,11 +265,12 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == TAG_EDITOR_REQUEST) { - refresh(); + reload(); setResult(RESULT_OK); } } + @NonNull @Override public MaterialCab openCab(int menuRes, @NonNull final MaterialCab.Callback callback) { if (cab != null && cab.isActive()) cab.finish(); @@ -317,7 +311,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements @Override public void onMediaStoreChanged() { super.onMediaStoreChanged(); - refresh(); + reload(); } @Override @@ -325,4 +319,53 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements super.setStatusbarColor(color); setLightStatusbar(false); } + + private void setAlbum(Album album) { + this.album = album; + loadAlbumCover(); + albumTitleView.setText(album.getTitle()); + adapter.swapDataSet(album.songs); + } + + private Album getAlbum() { + if (album == null) album = new Album(); + return album; + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new AsyncAlbumLoader(this, args.getInt(EXTRA_ALBUM_ID)); + } + + @DebugLog + @Override + public void onLoadFinished(Loader loader, Album data) { + supportStartPostponedEnterTransition(); + setAlbum(data); + if (getAlbum().songs.isEmpty()) { + finish(); + } + } + + @DebugLog + @Override + public void onLoaderReset(Loader loader) { + this.album = new Album(); + adapter.swapDataSet(album.songs); + } + + private static class AsyncAlbumLoader extends WrappedAsyncTaskLoader { + private final int albumId; + + public AsyncAlbumLoader(Context context, int albumId) { + super(context); + this.albumId = albumId; + } + + @DebugLog + @Override + public Album loadInBackground() { + return AlbumLoader.getAlbum(getContext(), albumId); + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java index 3440fe7e..81c9e567 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java @@ -1,10 +1,13 @@ package com.kabouzeid.gramophone.ui.activities; +import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; @@ -45,6 +48,7 @@ import com.kabouzeid.gramophone.loader.ArtistAlbumLoader; import com.kabouzeid.gramophone.loader.ArtistLoader; import com.kabouzeid.gramophone.loader.ArtistSongLoader; import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks; +import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader; import com.kabouzeid.gramophone.model.Album; import com.kabouzeid.gramophone.model.Artist; import com.kabouzeid.gramophone.model.Song; @@ -58,6 +62,7 @@ import java.util.ArrayList; import butterknife.Bind; import butterknife.ButterKnife; +import hugo.weaving.DebugLog; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -65,9 +70,10 @@ import retrofit2.Response; /** * Be careful when changing things in this Activity! */ -public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implements PaletteColorHolder, CabHolder { +public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implements PaletteColorHolder, CabHolder, LoaderManager.LoaderCallbacks { public static final String TAG = ArtistDetailActivity.class.getSimpleName(); + private static final int LOADER_ID = 1; public static final String EXTRA_ARTIST_ID = "extra_artist_id"; @@ -92,7 +98,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement private int toolbarColor; private float toolbarAlpha; - private Artist artist; + private ArtistData artistData; @Nullable private Spanned biography; private HorizontalAlbumAdapter albumAdapter; @@ -106,13 +112,16 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement setDrawUnderStatusbar(true); ButterKnife.bind(this); + supportPostponeEnterTransition(); + lastFMRestClient = new LastFMRestClient(this); - getArtistFromIntentExtras(); initViews(); setUpObservableListViewParams(); setUpViews(); setUpToolbar(); + + getSupportLoaderManager().initLoader(LOADER_ID, getIntent().getExtras(), this); } @Override @@ -163,11 +172,8 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement } private void setUpViews() { - artistName.setText(artist.name); - setUpArtistImageAndApplyPalette(false); setUpSongListView(); setUpAlbumRecyclerView(); - loadBiography(); } private void setUpSongListView() { @@ -175,7 +181,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement songListView.setScrollViewCallbacks(observableScrollViewCallbacks); songListView.addHeaderView(songListHeader); - songAdapter = new ArtistSongAdapter(this, loadSongDataSet(), this); + songAdapter = new ArtistSongAdapter(this, getArtistData().songs, this); songListView.setAdapter(songAdapter); final View contentView = getWindow().getDecorView().findViewById(android.R.id.content); @@ -194,7 +200,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement private void setUpAlbumRecyclerView() { albumRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); - albumAdapter = new HorizontalAlbumAdapter(this, loadAlbumDataSet(), this); + albumAdapter = new HorizontalAlbumAdapter(this, getArtistData().albums, this); albumRecyclerView.setAdapter(albumAdapter); albumAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { @Override @@ -205,21 +211,12 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement }); } - private void reloadDataSets() { - songAdapter.swapDataSet(loadSongDataSet()); - albumAdapter.swapDataSet(loadAlbumDataSet()); - } - - private ArrayList loadSongDataSet() { - return ArtistSongLoader.getArtistSongList(this, artist.id); - } - - private ArrayList loadAlbumDataSet() { - return ArtistAlbumLoader.getAlbums(this, artist.id); + private void reload() { + getSupportLoaderManager().restartLoader(LOADER_ID, getIntent().getExtras(), this); } private void loadBiography() { - lastFMRestClient.getApiService().getArtistInfo(artist.name, null).enqueue(new Callback() { + lastFMRestClient.getApiService().getArtistInfo(getArtistData().artist.name, null).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { LastFmArtist lastFmArtist = response.body(); @@ -243,23 +240,23 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement private MaterialDialog getBiographyDialog() { return new MaterialDialog.Builder(ArtistDetailActivity.this) - .title(artist.name) + .title(getArtistData().artist.name) .content(biography != null ? biography : "") .positiveText(android.R.string.ok) .build(); } - private void setUpArtistImageAndApplyPalette(final boolean forceDownload) { + private void loadArtistImage(final boolean forceDownload) { if (forceDownload) { - ArtistSignatureUtil.getInstance(this).updateArtistSignature(artist.name); + ArtistSignatureUtil.getInstance(this).updateArtistSignature(getArtistData().artist.name); } Glide.with(this) - .load(new ArtistImage(artist.name, forceDownload)) + .load(new ArtistImage(getArtistData().artist.name, forceDownload)) .asBitmap() .transcode(new BitmapPaletteTranscoder(this), BitmapPaletteWrapper.class) .diskCacheStrategy(DiskCacheStrategy.SOURCE) .placeholder(R.drawable.default_artist_image) - .signature(ArtistSignatureUtil.getInstance(this).getArtistSignature(artist.name)) + .signature(ArtistSignatureUtil.getInstance(this).getArtistSignature(getArtistData().artist.name)) .dontAnimate() .override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) .listener(new RequestListener() { @@ -291,7 +288,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { - reloadDataSets(); + reload(); } } @@ -308,15 +305,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement setTaskDescriptionColor(color); } - private void getArtistFromIntentExtras() { - Bundle intentExtras = getIntent().getExtras(); - final int artistId = intentExtras.getInt(EXTRA_ARTIST_ID); - artist = ArtistLoader.getArtist(this, artistId); - if (artist.id == -1) { - finish(); - } - } - private void setUpToolbar() { setSupportActionBar(toolbar); //noinspection ConstantConditions @@ -355,12 +343,13 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement return true; case R.id.action_re_download_artist_image: Toast.makeText(ArtistDetailActivity.this, getResources().getString(R.string.updating), Toast.LENGTH_SHORT).show(); - setUpArtistImageAndApplyPalette(true); + loadArtistImage(true); return true; } return super.onOptionsItemSelected(item); } + @NonNull @Override public MaterialCab openCab(int menuRes, @NonNull final MaterialCab.Callback callback) { if (cab != null && cab.isActive()) cab.finish(); @@ -401,7 +390,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement @Override public void onMediaStoreChanged() { super.onMediaStoreChanged(); - reloadDataSets(); + reload(); } @Override @@ -409,4 +398,77 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement super.setStatusbarColor(color); setLightStatusbar(false); } + + private void setArtistData(ArtistData artistData) { + this.artistData = artistData; + loadArtistImage(false); + loadBiography(); + artistName.setText(artistData.artist.name); + songAdapter.swapDataSet(artistData.songs); + albumAdapter.swapDataSet(artistData.albums); + } + + private ArtistData getArtistData() { + if (artistData == null) artistData = new ArtistData(); + return artistData; + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new AsyncArtistDataLoader(this, args.getInt(EXTRA_ARTIST_ID)); + } + + @DebugLog + @Override + public void onLoadFinished(Loader loader, ArtistData data) { + supportStartPostponedEnterTransition(); + setArtistData(data); + if (getArtistData().albums.isEmpty()) { + finish(); + } + } + + @DebugLog + @Override + public void onLoaderReset(Loader loader) { + this.artistData = new ArtistData(); + songAdapter.swapDataSet(artistData.songs); + albumAdapter.swapDataSet(artistData.albums); + } + + private static class AsyncArtistDataLoader extends WrappedAsyncTaskLoader { + private final int artistId; + + public AsyncArtistDataLoader(Context context, int artistId) { + super(context); + this.artistId = artistId; + } + + @DebugLog + @Override + public ArtistData loadInBackground() { + Artist artist = ArtistLoader.getArtist(getContext(), artistId); + ArrayList songs = ArtistSongLoader.getArtistSongList(getContext(), artist.id); + ArrayList albums = ArtistAlbumLoader.getAlbums(getContext(), artist.id); + return new ArtistData(artist, songs, albums); + } + } + + static class ArtistData { + public final Artist artist; + public final ArrayList songs; + public final ArrayList albums; + + private ArtistData() { + artist = new Artist(); + songs = new ArrayList<>(); + albums = new ArrayList<>(); + } + + private ArtistData(Artist artist, ArrayList songs, ArrayList albums) { + this.artist = artist; + this.songs = songs; + this.albums = albums; + } + } } \ No newline at end of file