From 521189060790bb99ef519056342840315991677b Mon Sep 17 00:00:00 2001 From: Hemanth S Date: Sun, 6 Sep 2020 12:48:47 +0530 Subject: [PATCH] Fix Album & Artist crash when no network --- .../fragments/albums/AlbumDetailsFragment.kt | 32 ++++++---- .../fragments/albums/AlbumDetailsViewModel.kt | 58 +++++-------------- .../artists/ArtistDetailsFragment.kt | 15 +++-- .../artists/ArtistDetailsViewModel.kt | 42 +++++--------- .../monkey/retromusic/{ => network}/Result.kt | 2 +- .../retromusic/repository/Repository.kt | 25 ++++++-- 6 files changed, 83 insertions(+), 91 deletions(-) rename app/src/main/java/code/name/monkey/retromusic/{ => network}/Result.kt (94%) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsFragment.kt index c047f6c3..2dfc5101 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsFragment.kt @@ -38,6 +38,7 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.SortOrder import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Artist +import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.model.LastFmAlbum import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.util.MusicUtil @@ -83,15 +84,7 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det startPostponedEnterTransition() showAlbum(it) }) - detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer { - loadArtistImage(it) - }) - detailsViewModel.getMoreAlbums().observe(viewLifecycleOwner, Observer { - moreAlbums(it) - }) - detailsViewModel.getAlbumInfo().observe(viewLifecycleOwner, Observer { - aboutAlbum(it) - }) + setupRecyclerView() artistImage.setOnClickListener { requireActivity().findNavController(R.id.fragment_container) @@ -172,8 +165,25 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det } loadAlbumCover(album) simpleSongAdapter.swapDataSet(album.songs) - detailsViewModel.loadArtist(album.artistId) - detailsViewModel.loadAlbumInfo(album) + detailsViewModel.getArtist(album.artistId).observe(viewLifecycleOwner, Observer { + loadArtistImage(it) + }) + /*detailsViewModel.getMoreAlbums().observe(viewLifecycleOwner, Observer { + moreAlbums(it) + })*/ + detailsViewModel.getAlbumInfo(album).observe(viewLifecycleOwner, Observer { result -> + when (result) { + is Result.Loading -> { + println("Loading") + } + is Result.Error -> { + println("Error") + } + is Result.Success -> { + aboutAlbum(result.data) + } + } + }) } private fun moreAlbums(albums: List) { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsViewModel.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsViewModel.kt index f698f882..3311046e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsViewModel.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/albums/AlbumDetailsViewModel.kt @@ -1,70 +1,44 @@ package code.name.monkey.retromusic.fragments.albums -import androidx.lifecycle.* +import androidx.lifecycle.LiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.liveData import code.name.monkey.retromusic.interfaces.MusicServiceEventListener import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Artist +import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.model.LastFmAlbum import code.name.monkey.retromusic.repository.RealRepository -import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.async -import kotlinx.coroutines.launch class AlbumDetailsViewModel( private val realRepository: RealRepository, private val albumId: Int ) : ViewModel(), MusicServiceEventListener { - private val _album = MutableLiveData() - private val _artist = MutableLiveData() - private val _lastFmAlbum = MutableLiveData() - private val _moreAlbums = MutableLiveData>() - fun getAlbum(): LiveData = liveData(IO) { val album = realRepository.albumByIdAsync(albumId) emit(album) } - fun getArtist(): LiveData = _artist - fun getAlbumInfo(): LiveData = _lastFmAlbum - fun getMoreAlbums(): LiveData> = _moreAlbums - - init { - loadAlbumDetails() - } - - fun getAlbum2() = liveData(context = viewModelScope.coroutineContext + IO) { - val album = realRepository.albumByIdAsync(albumId) - emit(album) - } - - private fun loadAlbumDetails() = viewModelScope.launch(IO) { - val album = loadAlbumAsync.await() ?: throw NullPointerException("Album couldn't found") - _album.postValue(album) - } - - fun loadAlbumInfo(album: Album) = viewModelScope.launch(IO) { - val lastFmAlbum = realRepository.albumInfo(album.artistName ?: "-", album.title ?: "-") - _lastFmAlbum.postValue(lastFmAlbum) - } - - fun loadArtist(artistId: Int) = viewModelScope.launch(IO) { + fun getArtist(artistId: Int): LiveData = liveData(IO) { val artist = realRepository.artistById(artistId) - _artist.postValue(artist) - - artist.albums?.filter { item -> item.id != albumId }?.let { albums -> - if (albums.isNotEmpty()) _moreAlbums.postValue(albums) - } + emit(artist) } - private val loadAlbumAsync: Deferred - get() = viewModelScope.async(IO) { - realRepository.albumByIdAsync(albumId) + fun getAlbumInfo(album: Album): LiveData> = liveData { + emit(Result.Loading) + emit( realRepository.albumInfo(album.artistName ?: "-", album.title ?: "-")) + } + + fun getMoreAlbums(artist: Artist): LiveData> = liveData(IO) { + artist.albums?.filter { item -> item.id != albumId }?.let { albums -> + if (albums.isNotEmpty()) emit(albums) } + } override fun onMediaStoreChanged() { - loadAlbumDetails() + } override fun onServiceConnected() {} diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsFragment.kt index f9db60bf..91743de4 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsFragment.kt @@ -32,6 +32,7 @@ import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.SingleColorTarget import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Artist +import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.model.LastFmArtist import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.util.CustomArtistImageUtil @@ -77,9 +78,7 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d showArtist(it) startPostponedEnterTransition() }) - detailsViewModel.getArtistInfo().observe(viewLifecycleOwner, Observer { - artistInfo(it) - }) + playAction.apply { setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) } @@ -140,6 +139,7 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d albumTitle.text = albumText songAdapter.swapDataSet(artist.songs.sortedBy { it.trackNumber }) artist.albums?.let { albumAdapter.swapDataSet(it) } + } private fun loadBiography( @@ -148,7 +148,14 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d ) { biography = null this.lang = lang - detailsViewModel.loadBiography(name, lang, null) + detailsViewModel.getArtistInfo(name, lang, null) + .observe(viewLifecycleOwner, Observer { result -> + when (result) { + is Result.Loading -> println("Loading") + is Result.Error -> println("Error") + is Result.Success -> artistInfo(result.data) + } + }) } private fun artistInfo(lastFmArtist: LastFmArtist?) { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsViewModel.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsViewModel.kt index f2ee5fe6..89039735 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsViewModel.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/ArtistDetailsViewModel.kt @@ -1,51 +1,37 @@ package code.name.monkey.retromusic.fragments.artists import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.lifecycle.liveData import code.name.monkey.retromusic.interfaces.MusicServiceEventListener import code.name.monkey.retromusic.model.Artist +import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.model.LastFmArtist import code.name.monkey.retromusic.repository.RealRepository -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.launch +import kotlinx.coroutines.Dispatchers.IO class ArtistDetailsViewModel( private val realRepository: RealRepository, private val artistId: Int ) : ViewModel(), MusicServiceEventListener { - private val loadArtistDetailsAsync: Deferred - get() = viewModelScope.async(Dispatchers.IO) { - realRepository.artistById(artistId) - } - - private val _artist = MutableLiveData() - private val _lastFmArtist = MutableLiveData() - - fun getArtist(): LiveData = _artist - fun getArtistInfo(): LiveData = _lastFmArtist - - init { - loadArtistDetails() + fun getArtist(): LiveData = liveData(IO) { + val artist = realRepository.artistById(artistId) + emit(artist) } - private fun loadArtistDetails() = viewModelScope.launch { - val artist = - loadArtistDetailsAsync.await() ?: throw NullPointerException("Album couldn't found") - _artist.postValue(artist) - } - - fun loadBiography(name: String, lang: String?, cache: String?) = viewModelScope.launch { + fun getArtistInfo( + name: String, + lang: String?, + cache: String? + ): LiveData> = liveData(IO) { + emit(Result.Loading) val info = realRepository.artistInfo(name, lang, cache) - _lastFmArtist.postValue(info) + emit(info) } override fun onMediaStoreChanged() { - loadArtistDetails() + getArtist() } override fun onServiceConnected() {} diff --git a/app/src/main/java/code/name/monkey/retromusic/Result.kt b/app/src/main/java/code/name/monkey/retromusic/network/Result.kt similarity index 94% rename from app/src/main/java/code/name/monkey/retromusic/Result.kt rename to app/src/main/java/code/name/monkey/retromusic/network/Result.kt index 4c241a14..05211fd3 100644 --- a/app/src/main/java/code/name/monkey/retromusic/Result.kt +++ b/app/src/main/java/code/name/monkey/retromusic/network/Result.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package code.name.monkey.retromusic +package code.name.monkey.retromusic.network /** * Generic class that holds the network state diff --git a/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt b/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt index 06478f49..dcd94ff5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt +++ b/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt @@ -21,6 +21,7 @@ import code.name.monkey.retromusic.db.* import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.smartplaylist.NotPlayedPlaylist import code.name.monkey.retromusic.network.LastFMService +import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.model.LastFmAlbum import code.name.monkey.retromusic.network.model.LastFmArtist import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -48,8 +49,8 @@ interface Repository { suspend fun search(query: String?): MutableList suspend fun getPlaylistSongs(playlist: Playlist): List suspend fun getGenre(genreId: Int): List - suspend fun artistInfo(name: String, lang: String?, cache: String?): LastFmArtist - suspend fun albumInfo(artist: String, album: String): LastFmAlbum + suspend fun artistInfo(name: String, lang: String?, cache: String?): Result + suspend fun albumInfo(artist: String, album: String): Result suspend fun artistById(artistId: Int): Artist suspend fun recentArtists(): List suspend fun topArtists(): List @@ -110,7 +111,9 @@ class RealRepository( override suspend fun fetchAlbums(): List = albumRepository.albums() override suspend fun albumByIdAsync(albumId: Int): Album = albumRepository.album(albumId) + override fun albumById(albumId: Int): Album = albumRepository.album(albumId) + override suspend fun fetchArtists(): List = artistRepository.artists() override suspend fun albumArtists(): List = artistRepository.albumArtists() @@ -147,17 +150,29 @@ class RealRepository( name: String, lang: String?, cache: String? - ): LastFmArtist = lastFMService.artistInfo(name, lang, cache) + ): Result { + return try { + Result.Success(lastFMService.artistInfo(name, lang, cache)) + } catch (e: Exception) { + Result.Error + } + } override suspend fun albumInfo( artist: String, album: String - ): LastFmAlbum = lastFMService.albumInfo(artist, album) + ): Result { + return try { + val lastFmAlbum = lastFMService.albumInfo(artist, album) + Result.Success(lastFmAlbum) + } catch (e: Exception) { + Result.Error + } + } @ExperimentalCoroutinesApi override suspend fun homeSectionsFlow(): Flow>> { val homes = MutableStateFlow>>(value = Result.Loading) - println("homeSections:Loading") val homeSections = mutableListOf() val sections = listOf( topArtistsHome(),