mograte MyListFragment to use a simple ViewModel
fixes crashes in MyListFragment if the User closes the fragment with a loading job still running, part of #56
This commit is contained in:
parent
5f609d4c33
commit
17dbe945e5
|
@ -1,17 +1,21 @@
|
|||
package org.mosad.teapod.ui.activity.main.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import kotlinx.coroutines.launch
|
||||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.databinding.FragmentMyListsBinding
|
||||
import org.mosad.teapod.parser.crunchyroll.Crunchyroll
|
||||
import org.mosad.teapod.ui.activity.main.viewmodel.MyListsFragmentViewModel
|
||||
import org.mosad.teapod.util.toItemMediaList
|
||||
|
||||
class MyListsFragment : Fragment() {
|
||||
|
@ -19,6 +23,8 @@ class MyListsFragment : Fragment() {
|
|||
private lateinit var binding: FragmentMyListsBinding
|
||||
private lateinit var pagerAdapter: FragmentStateAdapter
|
||||
|
||||
private val model: MyListsFragmentViewModel by viewModels()
|
||||
|
||||
private val fragments = arrayListOf<Fragment>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
|
@ -33,7 +39,6 @@ class MyListsFragment : Fragment() {
|
|||
pagerAdapter = ScreenSlidePagerAdapter(this)
|
||||
binding.pagerMyLists.adapter = pagerAdapter
|
||||
|
||||
// TODO is position 0 always episodes? (and 1 always similar titles)
|
||||
TabLayoutMediator(binding.tabMyLists, binding.pagerMyLists) { tab, position ->
|
||||
tab.text = when(position) {
|
||||
0 -> getString(R.string.my_list)
|
||||
|
@ -43,15 +48,33 @@ class MyListsFragment : Fragment() {
|
|||
}
|
||||
}.attach()
|
||||
|
||||
lifecycleScope.launch {
|
||||
val items = Crunchyroll.watchlist(50)
|
||||
|
||||
MediaFragmentSimilar(items.toItemMediaList()).also {
|
||||
fragments.add(it)
|
||||
pagerAdapter.notifyItemInserted(fragments.indexOf(it))
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
model.onUiState(viewLifecycleOwner.lifecycleScope) { uiState ->
|
||||
when (uiState) {
|
||||
is MyListsFragmentViewModel.UiState.Normal -> bindUiStateNormal(uiState)
|
||||
is MyListsFragmentViewModel.UiState.Loading -> bindUiStateLoading()
|
||||
is MyListsFragmentViewModel.UiState.Error -> bindUiStateError(uiState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUiStateNormal(uiState: MyListsFragmentViewModel.UiState.Normal) {
|
||||
MediaFragmentSimilar(uiState.watchlistItems.toItemMediaList()).also {
|
||||
fragments.add(it)
|
||||
pagerAdapter.notifyItemInserted(fragments.indexOf(it))
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUiStateLoading() {
|
||||
// currently not used
|
||||
}
|
||||
|
||||
private fun bindUiStateError(uiState: MyListsFragmentViewModel.UiState.Error) {
|
||||
// currently not used
|
||||
Log.e(javaClass.name, "A error occurred while loading a UiState: ${uiState.message}")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,7 +32,7 @@ import kotlinx.coroutines.launch
|
|||
import org.mosad.teapod.parser.crunchyroll.*
|
||||
import kotlin.random.Random
|
||||
|
||||
class HomeViewModel : ViewModel() {
|
||||
class HomeViewModel : ViewModel() {
|
||||
|
||||
private val WATCHLIST_LENGTH = 50
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package org.mosad.teapod.ui.activity.main.viewmodel
|
||||
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.mosad.teapod.parser.crunchyroll.Crunchyroll
|
||||
import org.mosad.teapod.parser.crunchyroll.Item
|
||||
|
||||
class MyListsFragmentViewModel : ViewModel() {
|
||||
|
||||
private val WATCHLIST_LENGTH = 50
|
||||
|
||||
private val uiState = MutableStateFlow<UiState>(UiState.Loading)
|
||||
|
||||
sealed class UiState {
|
||||
object Loading : UiState()
|
||||
data class Normal(
|
||||
val watchlistItems: List<Item>
|
||||
) : UiState()
|
||||
data class Error(val message: String?) : UiState()
|
||||
}
|
||||
|
||||
init {
|
||||
load()
|
||||
}
|
||||
|
||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||
scope.launch { uiState.collect { collector(it) } }
|
||||
}
|
||||
|
||||
fun load() {
|
||||
viewModelScope.launch {
|
||||
uiState.emit(UiState.Loading)
|
||||
try {
|
||||
// run the loading in parallel to speed up the process
|
||||
val watchlistJob = viewModelScope.async { Crunchyroll.watchlist(WATCHLIST_LENGTH).data }
|
||||
uiState.emit(
|
||||
UiState.Normal(watchlistJob.await())
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
uiState.emit(UiState.Error(e.message))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue