Replace LiveData with StateFlow
This commit is contained in:
@@ -19,6 +19,8 @@ import org.koitharu.kotatsu.core.ui.list.decor.TypedSpacingItemDecoration
|
||||
import org.koitharu.kotatsu.core.util.ext.disposeImageRequest
|
||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding
|
||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService
|
||||
@@ -64,7 +66,7 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
|
||||
viewModel.content.observe(this, listAdapter::setItems)
|
||||
viewModel.user.observe(this, this::onUserChanged)
|
||||
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
|
||||
viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
|
||||
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
|
||||
viewModel.onLoggedOut.observe(this) {
|
||||
finishAfterTransition()
|
||||
}
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
package org.koitharu.kotatsu.scrobbling.common.ui.config
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.util.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.core.util.asFlowLiveData
|
||||
import org.koitharu.kotatsu.core.util.ext.emitValue
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.onFirst
|
||||
import org.koitharu.kotatsu.core.util.ext.require
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
@@ -40,34 +41,34 @@ class ScrobblerConfigViewModel @Inject constructor(
|
||||
|
||||
val titleResId = scrobbler.scrobblerService.titleResId
|
||||
|
||||
val user = MutableLiveData<ScrobblerUser?>(null)
|
||||
val onLoggedOut = SingleLiveEvent<Unit>()
|
||||
val user = MutableStateFlow<ScrobblerUser?>(null)
|
||||
val onLoggedOut = MutableEventFlow<Unit>()
|
||||
|
||||
val content = scrobbler.observeAllScrobblingInfo()
|
||||
.onStart { loadingCounter.increment() }
|
||||
.onFirst { loadingCounter.decrement() }
|
||||
.catch { errorEvent.postCall(it) }
|
||||
.catch { errorEvent.call(it) }
|
||||
.map { buildContentList(it) }
|
||||
.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList())
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
init {
|
||||
scrobbler.user
|
||||
.onEach { user.emitValue(it) }
|
||||
.onEach { user.value = it }
|
||||
.launchIn(viewModelScope + Dispatchers.Default)
|
||||
}
|
||||
|
||||
fun onAuthCodeReceived(authCode: String) {
|
||||
launchLoadingJob(Dispatchers.Default) {
|
||||
val newUser = scrobbler.authorize(authCode)
|
||||
user.emitValue(newUser)
|
||||
user.value = newUser
|
||||
}
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
launchLoadingJob(Dispatchers.Default) {
|
||||
scrobbler.logout()
|
||||
user.emitValue(null)
|
||||
onLoggedOut.emitCall(Unit)
|
||||
user.value = null
|
||||
onLoggedOut.call(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback
|
||||
import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
import org.koitharu.kotatsu.core.util.ext.withArgs
|
||||
import org.koitharu.kotatsu.databinding.SheetScrobblingSelectorBinding
|
||||
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
|
||||
@@ -72,8 +74,8 @@ class ScrobblingSelectorBottomSheet :
|
||||
decoration.checkedItemId = it
|
||||
binding.recyclerView.invalidateItemDecorations()
|
||||
}
|
||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
||||
viewModel.onClose.observe(viewLifecycleOwner) {
|
||||
viewModel.onError.observeEvent(viewLifecycleOwner, ::onError)
|
||||
viewModel.onClose.observeEvent(viewLifecycleOwner) {
|
||||
dismiss()
|
||||
}
|
||||
viewModel.selectedScrobblerIndex.observe(viewLifecycleOwner) { index ->
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.koitharu.kotatsu.scrobbling.common.ui.selector
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
||||
@@ -9,14 +7,17 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.core.parser.MangaIntent
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.util.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.core.util.asFlowLiveData
|
||||
import org.koitharu.kotatsu.core.util.ext.emitValue
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.require
|
||||
import org.koitharu.kotatsu.core.util.ext.requireValue
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
@@ -39,7 +40,7 @@ class ScrobblingSelectorViewModel @Inject constructor(
|
||||
|
||||
val availableScrobblers = scrobblers.filter { it.isAvailable }
|
||||
|
||||
val selectedScrobblerIndex = MutableLiveData(0)
|
||||
val selectedScrobblerIndex = MutableStateFlow(0)
|
||||
|
||||
private val scrobblerMangaList = MutableStateFlow<List<ScrobblerManga>>(emptyList())
|
||||
private val hasNextPage = MutableStateFlow(true)
|
||||
@@ -51,7 +52,7 @@ class ScrobblingSelectorViewModel @Inject constructor(
|
||||
private val currentScrobbler: Scrobbler
|
||||
get() = availableScrobblers[selectedScrobblerIndex.requireValue()]
|
||||
|
||||
val content: LiveData<List<ListModel>> = combine(
|
||||
val content: StateFlow<List<ListModel>> = combine(
|
||||
scrobblerMangaList,
|
||||
listError,
|
||||
hasNextPage,
|
||||
@@ -71,11 +72,11 @@ class ScrobblingSelectorViewModel @Inject constructor(
|
||||
},
|
||||
)
|
||||
}
|
||||
}.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
|
||||
|
||||
val selectedItemId = MutableLiveData(NO_ID)
|
||||
val searchQuery = MutableLiveData(manga.title)
|
||||
val onClose = SingleLiveEvent<Unit>()
|
||||
val selectedItemId = MutableStateFlow(NO_ID)
|
||||
val searchQuery = MutableStateFlow(manga.title)
|
||||
val onClose = MutableEventFlow<Unit>()
|
||||
|
||||
val isEmpty: Boolean
|
||||
get() = scrobblerMangaList.value.isEmpty()
|
||||
@@ -130,13 +131,13 @@ class ScrobblingSelectorViewModel @Inject constructor(
|
||||
if (doneJob?.isActive == true) {
|
||||
return
|
||||
}
|
||||
val targetId = selectedItemId.value ?: NO_ID
|
||||
val targetId = selectedItemId.value
|
||||
if (targetId == NO_ID) {
|
||||
onClose.call(Unit)
|
||||
}
|
||||
doneJob = launchJob(Dispatchers.Default) {
|
||||
currentScrobbler.linkManga(manga.id, targetId)
|
||||
onClose.emitCall(Unit)
|
||||
onClose.call(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +156,7 @@ class ScrobblingSelectorViewModel @Inject constructor(
|
||||
try {
|
||||
val info = currentScrobbler.getScrobblingInfoOrNull(manga.id)
|
||||
if (info != null) {
|
||||
selectedItemId.emitValue(info.targetId)
|
||||
selectedItemId.value = info.targetId
|
||||
}
|
||||
} finally {
|
||||
loadList(append = false)
|
||||
|
||||
Reference in New Issue
Block a user