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