RxJava2问题:子Single返回的错误已在父Single处理仍被传播
多服务并行调用并合并结果的RxJava实现方案
看起来你正在用RxJava实现一个多服务数据合并的搜索功能,我帮你把这个思路补全并规范代码结构~
首先,核心思路是利用RxJava的Single.zip操作符来并行处理4个服务的请求,等所有服务返回结果(或错误默认值)后,再用Builder模式构建最终的SearchResult对象。完整的实现代码如下:
import io.reactivex.Single import io.reactivex.schedulers.Schedulers class Repository( private val service1: Service1, private val service2: Service2, private val service3: Service3, private val service4: Service4 ) { fun search(): Single<SearchResult> { // 初始化每个服务的请求流,处理线程调度和错误兜底 val service1Result = service1.search() .subscribeOn(Schedulers.io()) .onErrorReturnItem(emptyList()) // 根据实际返回类型设置默认值,比如空列表 val service2Result = service2.search() .subscribeOn(Schedulers.io()) .onErrorReturnItem(emptyMap()) // 假设返回Map类型,用空Map兜底 val service3Result = service3.search() .subscribeOn(Schedulers.io()) .onErrorReturnItem(Data3.getDefaultInstance()) // 单个对象类型用默认实例兜底 val service4Result = service4.search() .subscribeOn(Schedulers.io()) .onErrorReturnItem(emptySet()) // 集合类型用空集合兜底 // 合并四个流,所有请求完成后构建SearchResult return Single.zip( service1Result, service2Result, service3Result, service4Result ) { data1, data2, data3, data4 -> SearchResult.Builder() .data1(data1) .data2(data2) .data3(data3) .data4(data4) .build() } } } // 假设的相关类定义示例 data class SearchResult private constructor( val data1: List<Data1>, val data2: Map<String, Data2>, val data3: Data3, val data4: Set<Data4> ) { class Builder { var data1: List<Data1> = emptyList() var data2: Map<String, Data2> = emptyMap() var data3: Data3 = Data3.getDefaultInstance() var data4: Set<Data4> = emptySet() fun data1(value: List<Data1>) = apply { data1 = value } fun data2(value: Map<String, Data2>) = apply { data2 = value } fun data3(value: Data3) = apply { data3 = value } fun data4(value: Set<Data4>) = apply { data4 = value } fun build() = SearchResult(data1, data2, data3, data4) } } interface Service1 { fun search(): Single<List<Data1>> } interface Service2 { fun search(): Single<Map<String, Data2>> } interface Service3 { fun search(): Single<Data3> } interface Service4 { fun search(): Single<Set<Data4>> } data class Data1(val id: String) data class Data2(val name: String) data class Data3(val value: Int) { companion object { fun getDefaultInstance() = Data3(0) } } data class Data4(val tag: String)
关键细节说明:
- 并行执行:每个服务请求都通过
subscribeOn(Schedulers.io())指定IO线程执行,Single.zip会让这些请求并行发起,直到所有请求都完成才会进入合并回调 - 错误容错:每个流都添加了
onErrorReturnItem,确保单个服务请求失败时,不会导致整个合并流程崩溃,而是用预设的默认值继续执行 - 类型安全:
Single.zip的回调参数会自动匹配每个流的返回类型,避免手动类型转换的麻烦 - Builder模式:用Builder构建
SearchResult既清晰又灵活,尤其当结果类字段较多时,比直接构造函数更易维护
额外提示:
如果是Android项目,在订阅这个Single的时候,记得加上observeOn(AndroidSchedulers.mainThread())来切换回主线程更新UI;如果某个服务返回的是Observable或Maybe,可以先通过firstOrError()或toSingle(defaultValue)转换成Single再参与合并。
内容的提问来源于stack exchange,提问作者Kelevandos
相关产品推荐
相关产品推荐

