使用 RxJava
我们可以做这样的事情:
基础 View 模型
protected void subscribe(Completable completable, MutableLiveData<Response> response) {
mDisposable.add(
completable.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnSubscribe(disposable -> response.setValue(Response.loading()))
.doFinally(() -> response.setValue(Response.idle()))
.subscribe(
() -> response.setValue(Response.success(true)),
e -> response.setValue(Response.error(e))
)
);
}
protected <T> void subscribe(Single<T> single, MutableLiveData<Response> response) {
mDisposable.add(
single.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnSubscribe(disposable -> response.setValue(Response.loading()))
.doFinally(() -> response.setValue(Response.idle()))
.subscribe(
result -> response.setValue(Response.success(result)),
e -> response.setValue(Response.error(e))
)
);
}
然后,我们从存储库中获取Single/Complete
并将其传递给我们的自定义subscribe()
,然后我们获取带有数据的通用Result
(可选),处理异步请求的非常简单的方法。
我们如何抽象具有相似结构的coroutines
,而不是在ViewModel
的每个方法中编写Launch
并手动尝试/捕获错误?
最佳答案
我建议您在迁移到协程时,不要紧跟您已有的代码进行最少的调整,而是全面检查您的设计。
嵌入协程的一个重要原则是结构化并发。这不仅仅是关于协程作用域和取消,它也是关于 futures 的任何名称的使用(CompletionStage
、Deferred
、Task
、Single
或任何其他)。根据结构化并发, future 基本上等同于没有定义范围的 Activity 线程。你应该避免它们。
相反,您应该在启动站点提供的单个顶级代码块中启动新的并发工作的代码中明确划定位置。
到目前为止,这意味着您确实在从 Android 框架进入代码的每个入口点都有一个 launch
block ,由于面向回调的编程模型的本质。
但是,该 block 中的所有内容都应根据结构化并发进行编码。如果您只有一个网络调用要进行,则您的代码完全是顺序的:进行调用、获取响应、处理它。网络调用本身成为挂起函数,完成调用结果并且不接受回调。来自阻塞调用世界的所有传统设计模式都适用于此。
请参阅此处了解如何将协程与 LiveData
结合使用,它可以帮助您将设计映射到面向协程的设计:
https://developer.android.com/topic/libraries/architecture/coroutines#livedata
关于android - 抽象协程结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62951852/