Kotlin \ Android - LiveData 异步转换阻止之前的结果
Kotlin \ Android - LiveData async transformation prevent previous result
所以我有一个 LiveData,我将其转换为需要一段时间才能执行的异步函数(有时需要 2 秒或 4 秒)。
有时调用时间很长,有时非常快(取决于结果)有时是即时的(空结果)
问题是,如果我的 LiveData 中有 2 个连续的发射,有时第一个结果需要一段时间才能执行,而第二个结果需要一瞬间,然后它会在第一个之前显示第二个,然后用之前的计算覆盖结果,
我想要的是一个连续的效果。 (有点像 RxJava concatMap)
private val _state = query.mapAsync(viewModelScope) { searchString ->
if (searchString.isEmpty()) {
NoSearch
} else {
val results = repo.search(searchString)
if (results.isNotEmpty()) {
Results(results.map { mapToMainResult(it, searchString) })
} else {
NoResults
}
}
}
@MainThread
fun <X, Y> LiveData<X>.mapAsync(
scope: CoroutineScope,
mapFunction: androidx.arch.core.util.Function<X, Y>
): LiveData<Y> {
val result = MediatorLiveData<Y>()
result.addSource(this) { x ->
scope.launch(Dispatchers.IO) { result.postValue(mapFunction.apply(x)) }
}
return result
}
如何防止第二个结果覆盖第一个结果?
@MainThread
fun <X, Y> LiveData<X>.mapAsync(
scope: CoroutineScope,
mapFunction: (X) -> Y,
): LiveData<Y> = switchMap { value ->
liveData(scope.coroutineContext) {
withContext(Dispatchers.IO) {
emit(mapFunction(value))
}
}
}
所以我有一个 LiveData,我将其转换为需要一段时间才能执行的异步函数(有时需要 2 秒或 4 秒)。
有时调用时间很长,有时非常快(取决于结果)有时是即时的(空结果)
问题是,如果我的 LiveData 中有 2 个连续的发射,有时第一个结果需要一段时间才能执行,而第二个结果需要一瞬间,然后它会在第一个之前显示第二个,然后用之前的计算覆盖结果,
我想要的是一个连续的效果。 (有点像 RxJava concatMap)
private val _state = query.mapAsync(viewModelScope) { searchString ->
if (searchString.isEmpty()) {
NoSearch
} else {
val results = repo.search(searchString)
if (results.isNotEmpty()) {
Results(results.map { mapToMainResult(it, searchString) })
} else {
NoResults
}
}
}
@MainThread
fun <X, Y> LiveData<X>.mapAsync(
scope: CoroutineScope,
mapFunction: androidx.arch.core.util.Function<X, Y>
): LiveData<Y> {
val result = MediatorLiveData<Y>()
result.addSource(this) { x ->
scope.launch(Dispatchers.IO) { result.postValue(mapFunction.apply(x)) }
}
return result
}
如何防止第二个结果覆盖第一个结果?
@MainThread
fun <X, Y> LiveData<X>.mapAsync(
scope: CoroutineScope,
mapFunction: (X) -> Y,
): LiveData<Y> = switchMap { value ->
liveData(scope.coroutineContext) {
withContext(Dispatchers.IO) {
emit(mapFunction(value))
}
}
}