Mar*_*zon 2 android kotlin android-mvvm rx-java2 android-livedata
从数据源搜索项目时,我有以下 UI 流程:
Outcome.loading(true)Outcome.success(results)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()
}
}
Run Code Online (Sandbox Code Playgroud)
下面是我的成果类
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)
}
}
Run Code Online (Sandbox Code Playgroud)
你不应该让你的加载状态成为“双重”状态(真/假)。您的进度状态应该仅在加载时发送,然后您将进入成功或失败状态。最后永远不要回到加载状态。这样做你总是知道你的视图需要显示哪个状态。
这是从我的Android Conductor + MVVM + Dagger 项目模板中提取的示例,它使用了导体,但您可以用片段或活动替换导体控制器,这是相同的逻辑。
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>()
}
Run Code Online (Sandbox Code Playgroud)
视图模型:
@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()
}
}
Run Code Online (Sandbox Code Playgroud)
基础数据控制器(片段/活动/导体):
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)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3837 次 |
| 最近记录: |