Optimize LiveData from flows
This commit is contained in:
@@ -77,7 +77,7 @@ class DetailsViewModel(
|
||||
}
|
||||
)
|
||||
}
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext)
|
||||
}.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
init {
|
||||
launchLoadingJob(Dispatchers.Default) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.koitharu.kotatsu.favourites.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.*
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.view.updatePadding
|
||||
@@ -27,7 +26,6 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesBinding>(),
|
||||
private val editDelegate by lazy(LazyThreadSafetyMode.NONE) {
|
||||
CategoriesEditDelegate(requireContext(), this)
|
||||
}
|
||||
private var adapterState: Parcelable? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -49,25 +47,6 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesBinding>(),
|
||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
||||
}
|
||||
|
||||
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||
super.onViewStateRestored(savedInstanceState)
|
||||
// (savedInstanceState?.getParcelable(KEY_ADAPTER_STATE) ?: adapterState)?.let {
|
||||
// (binding.pager.adapter as FavouritesPagerAdapter).restoreState(it)
|
||||
// }
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
adapterState = (binding.pager.adapter as? FavouritesPagerAdapter)?.saveState()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
adapterState = (bindingOrNull()?.pager?.adapter as? FavouritesPagerAdapter)?.saveState()
|
||||
?: adapterState
|
||||
outState.putParcelable(KEY_ADAPTER_STATE, adapterState)
|
||||
}
|
||||
|
||||
override fun onWindowInsetsChanged(insets: Insets) {
|
||||
binding.tabs.updatePadding(
|
||||
left = insets.left,
|
||||
@@ -132,8 +111,6 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesBinding>(),
|
||||
|
||||
companion object {
|
||||
|
||||
private const val KEY_ADAPTER_STATE = "adapter_state"
|
||||
|
||||
fun newInstance() = FavouritesContainerFragment()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
package org.koitharu.kotatsu.favourites.ui.categories
|
||||
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
|
||||
class FavouritesCategoriesViewModel(
|
||||
private val repository: FavouritesRepository
|
||||
@@ -15,7 +14,7 @@ class FavouritesCategoriesViewModel(
|
||||
private var reorderJob: Job? = null
|
||||
|
||||
val categories = repository.observeCategories()
|
||||
.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext)
|
||||
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
fun createCategory(name: String) {
|
||||
launchJob(Dispatchers.Default) {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package org.koitharu.kotatsu.favourites.ui.categories.select
|
||||
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
|
||||
class MangaCategoriesViewModel(
|
||||
private val manga: Manga,
|
||||
@@ -26,7 +25,7 @@ class MangaCategoriesViewModel(
|
||||
isChecked = it.id in checked
|
||||
)
|
||||
}
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext)
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
fun setChecked(categoryId: Long, isChecked: Boolean) {
|
||||
launchJob(Dispatchers.Default) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
@@ -14,7 +13,7 @@ import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveData
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.onFirst
|
||||
|
||||
class FavouritesListViewModel(
|
||||
@@ -43,7 +42,7 @@ class FavouritesListViewModel(
|
||||
isLoading.postValue(false)
|
||||
}.catch {
|
||||
emit(listOf(it.toErrorState(canRetry = false)))
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext, listOf(LoadingState))
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
override fun onRefresh() = Unit
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.koitharu.kotatsu.history.domain.MangaWithHistory
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.*
|
||||
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveData
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.daysDiff
|
||||
import org.koitharu.kotatsu.utils.ext.onFirst
|
||||
import java.util.*
|
||||
@@ -51,7 +51,7 @@ class HistoryListViewModel(
|
||||
isLoading.postValue(false)
|
||||
}.catch {
|
||||
it.toErrorState(canRetry = false)
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext, listOf(LoadingState))
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
override fun onRefresh() = Unit
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
||||
private var paginationListener: PaginationScrollListener? = null
|
||||
private val spanResolver = MangaListSpanResolver()
|
||||
private val spanSizeLookup = SpanSizeLookup()
|
||||
private val listCommitCallback = Runnable {
|
||||
spanSizeLookup.invalidateCache()
|
||||
}
|
||||
open val isSwipeRefreshEnabled = true
|
||||
|
||||
protected abstract val viewModel: MangaListViewModel
|
||||
@@ -148,8 +151,7 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
||||
}
|
||||
|
||||
private fun onListChanged(list: List<ListModel>) {
|
||||
spanSizeLookup.invalidateCache()
|
||||
listAdapter?.items = list
|
||||
listAdapter?.setItems(list, listCommitCallback)
|
||||
}
|
||||
|
||||
private fun onError(e: Throwable) {
|
||||
@@ -178,7 +180,7 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
||||
|
||||
@CallSuper
|
||||
protected open fun onLoadingStateChanged(isLoading: Boolean) {
|
||||
binding.swipeRefreshLayout.isEnabled =
|
||||
binding.swipeRefreshLayout.isEnabled = binding.swipeRefreshLayout.isRefreshing ||
|
||||
isSwipeRefreshEnabled && !isLoading
|
||||
if (!isLoading) {
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.koitharu.kotatsu.list.ui
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
@@ -10,6 +9,7 @@ import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
|
||||
abstract class MangaListViewModel(
|
||||
private val settings: AppSettings
|
||||
@@ -21,16 +21,20 @@ abstract class MangaListViewModel(
|
||||
val gridScale = settings.observe()
|
||||
.filter { it == AppSettings.KEY_GRID_SIZE }
|
||||
.map { settings.gridSize / 100f }
|
||||
.onStart { emit(settings.gridSize / 100f) }
|
||||
.flowOn(Dispatchers.IO)
|
||||
.asLiveData(viewModelScope.coroutineContext)
|
||||
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.IO) {
|
||||
settings.gridSize / 100f
|
||||
}
|
||||
|
||||
protected fun createListModeFlow() = settings.observe()
|
||||
.filter { it == AppSettings.KEY_LIST_MODE }
|
||||
.map { settings.listMode }
|
||||
.onStart { emit(settings.listMode) }
|
||||
.distinctUntilChanged()
|
||||
.onEach { listMode.postValue(it) }
|
||||
.onEach {
|
||||
if (listMode.value != it) {
|
||||
listMode.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun onRefresh()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import coil.ImageLoader
|
||||
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
|
||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.ui.DateTimeAgo
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaGridModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListDetailedModel
|
||||
@@ -38,6 +39,10 @@ class MangaListAdapter(
|
||||
.addDelegate(ITEM_TYPE_EMPTY, emptyStateListAD())
|
||||
}
|
||||
|
||||
fun setItems(list: List<ListModel>, commitCallback: Runnable) {
|
||||
differ.submitList(list, commitCallback)
|
||||
}
|
||||
|
||||
private class DiffCallback : DiffUtil.ItemCallback<ListModel>() {
|
||||
|
||||
override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel) = when {
|
||||
@@ -50,6 +55,9 @@ class MangaListAdapter(
|
||||
oldItem is MangaGridModel && newItem is MangaGridModel -> {
|
||||
oldItem.id == newItem.id
|
||||
}
|
||||
oldItem is DateTimeAgo && newItem is DateTimeAgo -> {
|
||||
oldItem == newItem
|
||||
}
|
||||
else -> oldItem.javaClass == newItem.javaClass
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,10 @@ package org.koitharu.kotatsu.local.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
|
||||
@@ -24,6 +21,7 @@ import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.utils.MediaStoreCompat
|
||||
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
import org.koitharu.kotatsu.utils.ext.sub
|
||||
import java.io.IOException
|
||||
@@ -51,9 +49,7 @@ class LocalListViewModel(
|
||||
list.isEmpty() -> listOf(EmptyState(R.string.text_local_holder))
|
||||
else -> list.toUi(mode)
|
||||
}
|
||||
}.onStart {
|
||||
emit(listOf(LoadingState))
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext)
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
init {
|
||||
onRefresh()
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package org.koitharu.kotatsu.main.ui
|
||||
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import org.koitharu.kotatsu.base.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
@@ -11,6 +12,7 @@ import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.history.domain.HistoryRepository
|
||||
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
|
||||
class MainViewModel(
|
||||
private val historyRepository: HistoryRepository,
|
||||
@@ -24,9 +26,7 @@ class MainViewModel(
|
||||
.filter { it == AppSettings.KEY_SOURCES_ORDER || it == AppSettings.KEY_SOURCES_HIDDEN }
|
||||
.onStart { emit("") }
|
||||
.map { MangaProviderFactory.getSources(settings, includeHidden = false) }
|
||||
.distinctUntilChanged()
|
||||
.flowOn(Dispatchers.Default)
|
||||
.asLiveData(viewModelScope.coroutineContext)
|
||||
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
fun openLastReader() {
|
||||
launchLoadingJob {
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.net.Uri
|
||||
import android.util.LongSparseArray
|
||||
import android.webkit.URLUtil
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
@@ -58,7 +57,7 @@ class ReaderViewModel(
|
||||
chapterNumber = chapter?.number ?: 0,
|
||||
chaptersTotal = chapters.size()
|
||||
)
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext)
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
val content = MutableLiveData<ReaderContent>(ReaderContent(emptyList(), null))
|
||||
val manga: Manga?
|
||||
@@ -68,9 +67,7 @@ class ReaderViewModel(
|
||||
.filter { it == AppSettings.KEY_READER_ANIMATION }
|
||||
.map { settings.readerAnimation }
|
||||
.onStart { emit(settings.readerAnimation) }
|
||||
.distinctUntilChanged()
|
||||
.flowOn(Dispatchers.IO)
|
||||
.asLiveData(viewModelScope.coroutineContext)
|
||||
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.IO)
|
||||
|
||||
val onZoomChanged = SingleLiveEvent<Unit>()
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
@@ -15,7 +14,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.list.ui.MangaFilterConfig
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.*
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveData
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import java.util.*
|
||||
|
||||
class RemoteListViewModel(
|
||||
@@ -49,7 +48,7 @@ class RemoteListViewModel(
|
||||
result
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext, listOf(LoadingState))
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
init {
|
||||
loadList(false)
|
||||
|
||||
@@ -5,14 +5,13 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.*
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveData
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import java.util.*
|
||||
|
||||
class SearchViewModel(
|
||||
@@ -46,7 +45,7 @@ class SearchViewModel(
|
||||
result
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext, listOf(LoadingState))
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
init {
|
||||
loadList(append = false)
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.*
|
||||
import org.koitharu.kotatsu.search.domain.MangaSearchRepository
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveData
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.onFirst
|
||||
import java.util.*
|
||||
|
||||
@@ -46,7 +46,7 @@ class GlobalSearchViewModel(
|
||||
result
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext, listOf(LoadingState))
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
init {
|
||||
onRefresh()
|
||||
|
||||
@@ -8,7 +8,6 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.model.TrackingLogItem
|
||||
@@ -17,7 +16,7 @@ import org.koitharu.kotatsu.list.ui.model.LoadingFooter
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import org.koitharu.kotatsu.tracker.ui.model.toFeedItem
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveData
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.mapItems
|
||||
|
||||
class FeedViewModel(
|
||||
@@ -41,7 +40,7 @@ class FeedViewModel(
|
||||
isHasNextPage -> list + LoadingFooter
|
||||
else -> list
|
||||
}
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext, listOf(LoadingState))
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
init {
|
||||
loadList(append = false)
|
||||
|
||||
@@ -26,14 +26,40 @@ fun <T> LiveData<T>.observeWithPrevious(owner: LifecycleOwner, observer: Buffere
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Flow<T>.asLiveData(
|
||||
fun <T> Flow<T>.asLiveDataDistinct(
|
||||
context: CoroutineContext = EmptyCoroutineContext
|
||||
): LiveData<T> = liveData(context) {
|
||||
collect {
|
||||
if (it != latestValue) {
|
||||
emit(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Flow<T>.asLiveDataDistinct(
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
defaultValue: T
|
||||
): LiveData<T> = liveData(context) {
|
||||
): LiveData<T> = liveData(context, 0L) {
|
||||
if (latestValue == null) {
|
||||
emit(defaultValue)
|
||||
}
|
||||
collect {
|
||||
emit(it)
|
||||
if (it != latestValue) {
|
||||
emit(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Flow<T>.asLiveDataDistinct(
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
defaultValue: suspend () -> T
|
||||
): LiveData<T> = liveData(context) {
|
||||
if (latestValue == null) {
|
||||
emit(defaultValue())
|
||||
}
|
||||
collect {
|
||||
if (it != latestValue) {
|
||||
emit(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
package org.koitharu.kotatsu.widget.shelf
|
||||
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.widget.shelf.model.CategoryItem
|
||||
import java.util.*
|
||||
|
||||
@@ -27,7 +26,7 @@ class ShelfConfigViewModel(
|
||||
CategoryItem(it.id, it.title, selectedId == it.id)
|
||||
}
|
||||
list
|
||||
}.flowOn(Dispatchers.Default).asLiveData(viewModelScope.coroutineContext)
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
var checkedId: Long by selectedCategoryId::value
|
||||
}
|
||||
Reference in New Issue
Block a user