在我当前的Android项目中,我有一个对话框,用于从Web服务中检索对象列表并在列表中显示这些对象。但它有一个问题。 Web服务(在我的控制范围之外)并不是最快的,因此该过程需要一段时间,并且通常用户在此过程正在进行时更改设备的方向。现在,方向更改会导致原始webservice调用被取消并创建一个新的调用,但这不是我应该知道的。我希望对话框能够在方向更改发生时继续从Web服务加载,但我无法理解如何执行此操作。如何挂钩正在进行的调用并在视图(对话框)中显示此状态?任何建议表示赞赏。我已经玩过Android架构组件和kotlins密封类,将视图状态保存在视图观察到的一个livingata对象中,但是没有找到我喜欢的解决方案。
我相信很多开发人员都会使用RxJava来解决这类问题。这是我唯一的选择吗?
顺便说一下。目前我在我的项目中使用MVP架构。
修改
这是我取消作业的地方 - 如果收听者为空,则取消(我使用kotlin协同程序):
override fun getWorklist() {
job = onWorkerThread {
val result = repository.getResult().awaitResult()
onMainThread {
when (result) {
is Result.Ok -> listener?.onResult(result.getOrDefault(emptyList())) :? job.cancel()
// Any HTTP error
is Result.Error -> listener?.onHttpError(result.exception) :? job.cancel()
// Exception while request invocation
is Result.Exception -> listener?.onException(result.exception) :? job.cancel()
}
}
}
}
修改2
我已尝试使用此Android Arch ViewModel控制viewstate,但未在viewstate对象更改时触发MediatorLiveData对象。视图保持加载状态:
class MainModel : ViewModel() {
private var job: Job? = null
val viewState = MutableLiveData<MainViewState>().apply { value = Loading("Warsaw") }
val dataGetter = MediatorLiveData<MainViewState>().apply {
addSource(viewState, {
Log.d("MainModel", "Viewstate is: " + viewState.value.toString() + ")...")
when(it) {
is Loading -> {
Log.d("MainModel", "Launching coroutine...")
job = launch(UI) {
Log.d("MainModel", "Loading...")
val items = Repository.getWorklist()
Log.d("MainModel", "Charts retrieved...")
this@MainModel.viewState.postValue(Success(it.items))
Log.d("MainModel", "Posted update to viewstate...")
}
}
}
})
}
override fun onCleared() {
Log.d("MainModel", "Clearing ViewModel")
job?.cancel()
}
}
interface ViewState
sealed class MainViewState : ViewState
class Loading() : MainViewState()
class Error(val error: String) : MainViewState()
class Success(val items: List<WorklistItem>) : MainViewState()