如何在Android中压缩两个Observable?

时间:2019-02-13 22:56:08

标签: android kotlin rx-java

在我的应用程序中,我有两个服务,并且它们都有一个方法,该方法发出请求,然后返回不同类型的Observable。

我想在RecyclerView中显示一个列表,该列表由这两个Observable的组合结果组成。我对此进行了谷歌搜索,发现zip()方法似乎完全符合我的要求。我正在尝试实施它,但我不知道如何正确执行。

在谷歌搜索时,我想到了这个this article,似乎可以清楚地解释它。即使作者在使用Observables时使用Singles。

据我了解zip()的工作原理,我知道我必须传递要“压缩”的每个Observable,然后必须指定一个函数来构成最终的Observable,对吗?

到目前为止,这是我的代码:

interface InvitationService {
    @GET("foo/{userId}")
    fun getFooByUser(@Path("userId") userId: String): Observable<Response<ArrayList<Foo>>>
}

interface InvitationService {
    @GET("bar/{userId}")
    fun getBarByUser(@Path("userId") userId: String): Observable<Response<ArrayList<Bar>>>
}

class FooRemoteDataSource : FooDataSource {
    private var apiService: FooService

    fun getFooByUser(userId:String) {
        return apiService.getFooByUser(userId)
    }
}

class BarRemoteDataSource : BarDataSource {
    private var apiService: BarService

    fun getBarByUser(userId:String) {
        return apiService.getBarByUser(userId)
    }

}

class FooRepository(private val remoteDataSource: InvitationRemoteDataSource) : FooDataSource {

    override fun getFooByUser(userId: String): Observable<Response<ArrayList<Foo>>> {
        return remoteDataSource.getFooByUser(userId)
    }
}

class BarRepository(private val remoteDataSource: BarRemoteDataSource) : BarDataSource {

    override fun getBarByUser(userId: String): Observable<Response<ArrayList<Bar>>> {
        return remoteDataSource.getBarByUser(userId)
    }
}

这是我实际遇到的地方:

class ListPresenter(var listFragment: ListContract.View?, 
                        val fooRepository: FooRepository,
                        val barRepository: BarRepository) : ListContract.Presenter {

    fun start() {
        loadList()
    }

    private fun loadLists() {
        //HERE IS WHERE IM STUCK

        Observable.zip(fooRepository.getFooByUser(userId).subscribeOn(Schedulers.io()),
                barRepository.getBarByUser(userId).subscribeOn(Schedulers.io()),
                )

        // AFTER 'ZIPPING' THE OBSERVABLES 
        // I NEED TO UPDATE THE VIEW ACCORDINGLY
    }
}

我不知道如何正确调用zip(),我知道我必须传递一个函数,但我不明白,因为在上面链接的文章中作者使用的是Function3,因为他有3个可观察值

由于我只有2个,所以我不知道该怎么做。如果方法args内的逗号后有花括号,则需要我返回BiFunction<ArrayList<Foo>, ArrayList<Bar>>,这是我不知道如何指定的。

有人会向我解释吗?

2 个答案:

答案 0 :(得分:2)

对于Kotlin,您应该使用RxKotlin而不是RxJava。 BiFunctionFunction3来自RxJava。借助RxKotlin,您可以改用lambda。


  

据我了解zip()的工作原理,我知道我必须传递我要“压缩”的每个Observable,然后必须指定一个组成最终Observable的函数,对吗?

正确,这是一个最小的示例,演示了如何做到这一点。

示例1

val observable1 = listOf(1, 2, 3).toObservable()
val observable2 = listOf(4, 5, 6).toObservable()
val zipped = Observables.zip(observable1, observable2) { o1, o2 -> o1 * o2}

在此示例中,您有两个可观察值,每个可观察值都发出整数。您将它们传递给zip,并将其作为第三个参数传递一个lambda,该lambda定义了“合并它们”的方法。在这种情况下,它将它们相乘。

结果可观察到的zipped将发出:4、10和18。


示例2

在另一个示例中,将三个并非相同类型的可观察对象压缩在一起:

val obs1 = listOf("on", "tw", "thre").toObservable()
val obs2 = listOf("n", "o", "e").toObservable()
val obs3 = listOf(1, 2, 3).toObservable()
val zipped = Observables.zip(obs1, obs2, obs3) { o1, o2, o3 -> 
    "$o1$o2 = $o3"
}

这里,可观察结果的每个元素将是一个字符串:“一个= 1”,“两个= 2”,“三个= 3”

答案 1 :(得分:1)

使用BiFunction压缩两个不同类型的Observable

override fun getCommoditiesAndAddresses() {
    view.showProgress()
    view.hideViews()
    Observable.zip(Commo24Retrofit.createAuthService(RateAPIService::class.java)
            .getCommodities(),
            Commo24Retrofit.createAuthService(RateAPIService::class.java)
                    .getLocations(GetLocationsRequest(getOrgId())),
            BiFunction { commodityResponse: GetCommoditiesResponse, locationsResponse: GetLocationsResponse ->
                handleCommoditiesAndAddresses(commodityResponse, locationsResponse)
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                view.hideProgress()
                view.showViews()
                view.handleCommodities(it?.commodities)
                view.handleLocations(it?.locations)
            }, { throwable ->
                view.hideProgress()
                view.handleFailure(throwable.getErrorMessage(context))
            })
}

看,我如何处理响应:

private fun handleCommoditiesAndAddresses(commodityResponse: GetCommoditiesResponse, locationsResponse: GetLocationsResponse): CommoditiesAddresses {
        return CommoditiesAddresses(commodityResponse.commodityList, locationsResponse.addressList)
    }

在这里,检查API服务:

interface RateAPIService {

    @POST("get-org-address")
    fun getLocations(@Body getLocationsRequest: GetLocationsRequest): Observable<GetLocationsResponse>

    @POST("get-commodity-list")
    fun getCommodities(): Observable<GetCommoditiesResponse>
    }

如果有任何疑问,可以将其注释掉。