Fix isLoading LiveData
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.base.ui
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@@ -11,8 +12,14 @@ import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
|
||||
|
||||
abstract class BaseViewModel : ViewModel() {
|
||||
|
||||
val onError = SingleLiveEvent<Throwable>()
|
||||
val isLoading = CountedBooleanLiveData()
|
||||
protected val loadingCounter = CountedBooleanLiveData()
|
||||
protected val errorEvent = SingleLiveEvent<Throwable>()
|
||||
|
||||
val onError: LiveData<Throwable>
|
||||
get() = errorEvent
|
||||
|
||||
val isLoading: LiveData<Boolean>
|
||||
get() = loadingCounter
|
||||
|
||||
protected fun launchJob(
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
@@ -25,18 +32,18 @@ abstract class BaseViewModel : ViewModel() {
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
block: suspend CoroutineScope.() -> Unit
|
||||
): Job = viewModelScope.launch(context + createErrorHandler(), start) {
|
||||
isLoading.postValue(true)
|
||||
loadingCounter.increment()
|
||||
try {
|
||||
block()
|
||||
} finally {
|
||||
isLoading.postValue(false)
|
||||
loadingCounter.decrement()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createErrorHandler() = CoroutineExceptionHandler { _, throwable ->
|
||||
throwable.printStackTraceDebug()
|
||||
if (throwable !is CancellationException) {
|
||||
onError.postCall(throwable)
|
||||
errorEvent.postCall(throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,31 @@
|
||||
package org.koitharu.kotatsu.base.ui.util
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.annotation.AnyThread
|
||||
import androidx.lifecycle.LiveData
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class CountedBooleanLiveData : MutableLiveData<Boolean>(false) {
|
||||
class CountedBooleanLiveData : LiveData<Boolean>(false) {
|
||||
|
||||
private var counter = 0
|
||||
private val counter = AtomicInteger(0)
|
||||
|
||||
override fun setValue(value: Boolean) {
|
||||
if (value) {
|
||||
counter++
|
||||
} else {
|
||||
counter--
|
||||
@AnyThread
|
||||
fun increment() {
|
||||
if (counter.getAndIncrement() == 0) {
|
||||
postValue(true)
|
||||
}
|
||||
val newValue = counter > 0
|
||||
if (newValue != this.value) {
|
||||
super.setValue(newValue)
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun decrement() {
|
||||
if (counter.decrementAndGet() == 0) {
|
||||
postValue(false)
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun reset() {
|
||||
if (counter.getAndSet(0) != 0) {
|
||||
postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,13 @@ package org.koitharu.kotatsu.history.ui
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.domain.ReversibleHandle
|
||||
import org.koitharu.kotatsu.base.domain.plus
|
||||
@@ -23,8 +26,6 @@ import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.daysDiff
|
||||
import org.koitharu.kotatsu.utils.ext.onFirst
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class HistoryListViewModel(
|
||||
private val repository: HistoryRepository,
|
||||
@@ -55,8 +56,10 @@ class HistoryListViewModel(
|
||||
)
|
||||
else -> mapList(list, grouped, mode)
|
||||
}
|
||||
}.onStart {
|
||||
loadingCounter.increment()
|
||||
}.onFirst {
|
||||
isLoading.postValue(false)
|
||||
loadingCounter.decrement()
|
||||
}.catch {
|
||||
it.toErrorState(canRetry = false)
|
||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||
|
||||
@@ -136,7 +136,7 @@ class RemoteListViewModel(
|
||||
e.printStackTraceDebug()
|
||||
listError.value = e
|
||||
if (!mangaList.value.isNullOrEmpty()) {
|
||||
onError.postCall(e)
|
||||
errorEvent.postCall(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,19 +67,19 @@ class GlobalSearchViewModel(
|
||||
searchJob = repository.globalSearch(query)
|
||||
.catch { e ->
|
||||
listError.value = e
|
||||
isLoading.postValue(false)
|
||||
loadingCounter.reset()
|
||||
}.onStart {
|
||||
mangaList.value = null
|
||||
listError.value = null
|
||||
isLoading.postValue(true)
|
||||
loadingCounter.increment()
|
||||
hasNextPage.value = true
|
||||
}.onEmpty {
|
||||
mangaList.value = emptyList()
|
||||
}.onCompletion {
|
||||
isLoading.postValue(false)
|
||||
loadingCounter.reset()
|
||||
hasNextPage.value = false
|
||||
}.onFirst {
|
||||
isLoading.postValue(false)
|
||||
loadingCounter.reset()
|
||||
}.onEach {
|
||||
mangaList.value = mangaList.value?.plus(it) ?: listOf(it)
|
||||
}.launchIn(viewModelScope + Dispatchers.Default)
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
@@ -37,8 +38,10 @@ class SuggestionsViewModel(
|
||||
list.toUi(this, mode)
|
||||
}
|
||||
}
|
||||
}.onStart {
|
||||
loadingCounter.increment()
|
||||
}.onFirst {
|
||||
isLoading.postValue(false)
|
||||
loadingCounter.decrement()
|
||||
}.catch {
|
||||
it.toErrorState(canRetry = false)
|
||||
}.asLiveDataDistinct(
|
||||
|
||||
Reference in New Issue
Block a user