Fix Album & Artist crash when no network
This commit is contained in:
parent
e8549513bd
commit
5211890607
6 changed files with 83 additions and 91 deletions
|
@ -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>) {
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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?) {
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
|
@ -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(),
|
||||
|
|
Loading…
Reference in a new issue