android - 抽象协程结构

标签 android kotlin kotlin-coroutines

使用 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 的任何名称的使用(CompletionStageDeferredTaskSingle 或任何其他)。根据结构化并发, future 基本上等同于没有定义范围的 Activity 线程。你应该避免它们。

相反,您应该在启动站点提供的单个顶级代码块中启动新的并发工作的代码中明确划定位置。

到目前为止,这意味着您确实在从 Android 框架进入代码的每个入口点都有一个 launch block ,由于面向回调的编程模型的本质。

但是,该 block 中的所有内容都应根据结构化并发进行编码。如果您只有一个网络调用要进行,则您的代码完全是顺序的:进行调用、获取响应、处理它。网络调用本身成为挂起函数,完成调用结果并且不接受回调。来自阻塞调用世界的所有传统设计模式都适用于此。

请参阅此处了解如何将协程与 LiveData 结合使用,它可以帮助您将设计映射到面向协程的设计:

https://developer.android.com/topic/libraries/architecture/coroutines#livedata

关于android - 抽象协程结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62951852/

相关文章:

generics - 将通用 lambda 放入映射中

android - 为什么 ViewModel 和 Fragment 中的相同变量不同?

android - 唯一标识android复合 View 中的元素

java - 将 ksoap2 响应解析为 int 数组

android - 带有 Android 应用程序的 jdb - 无法打开源文件

kotlin - 在 Kotlin 中锁定互斥锁的正确方法

android - 如果我在暂停乐趣中启动 MediaRecorder.start() 并在 Android 中以正常乐趣启动 MediaRecorder.stop() 会导致错误吗?

java - 线性布局中的按钮垂直而不是水平显示?

json - 将扩展属性序列化为 JSON

kotlin - 如何截断 Kotlin 持续时间?