gpt4 book ai didi

android - 使用 ViewModel、LiveData 和 RxJava 在 recyclerview 中处理数据和加载指示器的正确方法

转载 作者:行者123 更新时间:2023-12-02 13:06:37 25 4
gpt4 key购买 nike

从数据源搜索项目时,我有以下 UI 流程:

  1. 在从源检索时显示进度指示器 -> 将 livedata 分配给 Outcome.loading(true)
  2. 显示结果 -> 分配 LiveData Outcome.success(results)
  3. 隐藏进度指示器 -> 分配 LiveData Outcome.loading(false)

现在的问题是当应用程序在后台时调用#2 和#3。恢复应用程序时,LiveData 观察者只被通知 #3 而不是 #2 导致未填充的 RecyclerView。

处理这种情况的正确方法是什么?

class SearchViewModel @Inject constructor(
private val dataSource: MusicInfoRepositoryInterface,
private val scheduler: Scheduler,
private val disposables: CompositeDisposable) : ViewModel() {

private val searchOutcome = MutableLiveData<Outcome<List<MusicInfo>>>()
val searchOutcomLiveData: LiveData<Outcome<List<MusicInfo>>>
get() = searchOutcome

fun search(searchText: String) {
Timber.d(".loadMusicInfos")
if(searchText.isBlank()) {
return
}

dataSource.search(searchText)
.observeOn(scheduler.mainThread())
.startWith(Outcome.loading(true))
.onErrorReturn { throwable -> Outcome.failure(throwable) }
.doOnTerminate { searchOutcome.value = Outcome.loading(false) }
.subscribeWith(object : DisposableSubscriber<Outcome<List<MusicInfo>>>() {
override fun onNext(outcome: Outcome<List<MusicInfo>>?) {
searchOutcome.value = outcome
}

override fun onError(e: Throwable) {
Timber.d(e, ".onError")
}

override fun onComplete() {
Timber.d(".onComplete")
}
}).addTo(disposables)
}

override fun onCleared() {
Timber.d(".onCleared")
super.onCleared()
disposables.clear()
}
}

下面是我的结果类

sealed class Outcome<T> {
data class Progress<T>(var loading: Boolean) : Outcome<T>()
data class Success<T>(var data: T) : Outcome<T>()
data class Failure<T>(val e: Throwable) : Outcome<T>()

companion object {
fun <T> loading(isLoading: Boolean): Outcome<T> = Progress(isLoading)

fun <T> success(data: T): Outcome<T> = Success(data)

fun <T> failure(e: Throwable): Outcome<T> = Failure(e)
}
}

最佳答案

您不应将加载状态设置为“双重”状态(真/假)。您的进度状态应仅在加载时分派(dispatch),然后您进入成功或失败状态。最后永远不要回到加载状态。这样做你总是知道你的 View 需要显示哪个状态。

  • 如果加载 -> 显示加载器
  • 如果成功 -> 隐藏加载器,显示数据
  • 如果错误 -> 隐藏加载器,显示错误

这是我的 Android Conductor + MVVM + Dagger project template 的示例摘录,它使用导体,但您可以将导体 Controller 替换为 fragment 或 Activity ,这是相同的逻辑。

sealed class DataRequestState<T> {
class Start<T> : DataRequestState<T>()
class Success<T>(var data: T) : DataRequestState<T>()
class Error<T>(val error: Throwable) : DataRequestState<T>()
}

View 模型:

@ControllerScope
class HomeControllerViewModel
@Inject
constructor(homeRepositoryManager: HomeRepositoryManager) : BaseControllerViewModel(),
DataFetchViewModel<Home> {
private val _dataFetchObservable: DataRequestLiveData<Home> =
DataRequestLiveData(homeRepositoryManager.home())
override val dataFetchObservable: LiveData<DataRequestState<Home>> = _dataFetchObservable

override fun refreshData() {
_dataFetchObservable.refresh()
}
}

基础数据 Controller ( fragment/Activity/导体):

abstract class BaseDataFetchController<VM, D> :
BaseViewModelController<VM>() where VM : BaseControllerViewModel, VM : DataFetchViewModel<D> {
override fun onViewCreated(view: View) {
super.onViewCreated(view)

viewModel.dataFetchObservable.observe(this, Observer {
it?.let {
when (it) {
is DataRequestState.Start -> dataFetchStart()
is DataRequestState.Success -> {
dataFetchSuccess(it.data)
dataFetchTerminate()
}
is DataRequestState.Error -> {
dataFetchError(it.error)
dataFetchTerminate()
}
}
}
})
}

protected abstract fun dataFetchStart()
protected abstract fun dataFetchSuccess(data: D)
protected abstract fun dataFetchError(throwable: Throwable)
}

关于android - 使用 ViewModel、LiveData 和 RxJava 在 recyclerview 中处理数据和加载指示器的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50271223/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com