Fix Album & Artist crash when no network

This commit is contained in:
Hemanth S 2020-09-06 12:48:47 +05:30
parent e8549513bd
commit 5211890607
6 changed files with 83 additions and 91 deletions

View file

@ -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<Album>) {

View file

@ -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<Album>()
private val _artist = MutableLiveData<Artist>()
private val _lastFmAlbum = MutableLiveData<LastFmAlbum>()
private val _moreAlbums = MutableLiveData<List<Album>>()
fun getAlbum(): LiveData<Album> = liveData(IO) {
val album = realRepository.albumByIdAsync(albumId)
emit(album)
}
fun getArtist(): LiveData<Artist> = _artist
fun getAlbumInfo(): LiveData<LastFmAlbum> = _lastFmAlbum
fun getMoreAlbums(): LiveData<List<Album>> = _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<Artist> = 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<Album?>
get() = viewModelScope.async(IO) {
realRepository.albumByIdAsync(albumId)
fun getAlbumInfo(album: Album): LiveData<Result<LastFmAlbum>> = liveData {
emit(Result.Loading)
emit( realRepository.albumInfo(album.artistName ?: "-", album.title ?: "-"))
}
fun getMoreAlbums(artist: Artist): LiveData<List<Album>> = liveData(IO) {
artist.albums?.filter { item -> item.id != albumId }?.let { albums ->
if (albums.isNotEmpty()) emit(albums)
}
}
override fun onMediaStoreChanged() {
loadAlbumDetails()
}
override fun onServiceConnected() {}

View file

@ -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?) {

View file

@ -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<Artist?>
get() = viewModelScope.async(Dispatchers.IO) {
realRepository.artistById(artistId)
}
private val _artist = MutableLiveData<Artist>()
private val _lastFmArtist = MutableLiveData<LastFmArtist>()
fun getArtist(): LiveData<Artist> = _artist
fun getArtistInfo(): LiveData<LastFmArtist> = _lastFmArtist
init {
loadArtistDetails()
fun getArtist(): LiveData<Artist> = 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<Result<LastFmArtist>> = 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() {}

View file

@ -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

View file

@ -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<Any>
suspend fun getPlaylistSongs(playlist: Playlist): List<Song>
suspend fun getGenre(genreId: Int): List<Song>
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<LastFmArtist>
suspend fun albumInfo(artist: String, album: String): Result<LastFmAlbum>
suspend fun artistById(artistId: Int): Artist
suspend fun recentArtists(): List<Artist>
suspend fun topArtists(): List<Artist>
@ -110,7 +111,9 @@ class RealRepository(
override suspend fun fetchAlbums(): List<Album> = 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<Artist> = artistRepository.artists()
override suspend fun albumArtists(): List<Artist> = artistRepository.albumArtists()
@ -147,17 +150,29 @@ class RealRepository(
name: String,
lang: String?,
cache: String?
): LastFmArtist = lastFMService.artistInfo(name, lang, cache)
): Result<LastFmArtist> {
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<LastFmAlbum> {
return try {
val lastFmAlbum = lastFMService.albumInfo(artist, album)
Result.Success(lastFmAlbum)
} catch (e: Exception) {
Result.Error
}
}
@ExperimentalCoroutinesApi
override suspend fun homeSectionsFlow(): Flow<Result<List<Home>>> {
val homes = MutableStateFlow<Result<List<Home>>>(value = Result.Loading)
println("homeSections:Loading")
val homeSections = mutableListOf<Home>()
val sections = listOf(
topArtistsHome(),