由于只能接受Observable <t>的一种通用类型,因此如何从Observable获取多种数据类型

时间:2018-09-26 07:30:39

标签: android rx-java rx-java2 rx-android

我们已经知道Observable只能有一个参数作为其泛型类型。可观察的 我假设我有2个网络调用,它们返回2种数据类型:UserResponseWorkResponse。 我想逐步调用这些API的2个,先是getUser然后是getWork。 最终,我订阅了它们,只得到了一种数据类型,显然是WorkResponse,因为getWork是上游Observable<WorkResponse>中的最后一个API调用。 但是在订阅代码块中,我想同时获取UserResponseWorkResponse。那我该如何实现呢?

1-有人说我应该创建一个包含UserResponseWorkResponse的容器类,然后才能从该容器中的预订代码块中获取这些数据类型。

2-创建一个临时变量来保存userResponse,然后从子代码块访问它,如下所示:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    var tempUserResponse: UserResponse? = null
    Observable.just("Prepare call API")
            .flatMap {
                apiGetUser()
            }.flatMap { userResponse ->
                tempUserResponse = userResponse // Save temporarily userResponse to pass it to subscribe code block
                apiGetWork()
            }.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { workResponse ->
                Log.e("TAG", "userResponse = " + tempUserResponse)
                Log.e("TAG", "workResponse = " + workResponse)
            }

}

private fun apiGetUser(): Observable<UserResponse> {
    // Fake API to get User
    return Observable.just(UserResponse())
}

private fun apiGetWork(): Observable<Work> {
    // Fake API to get Work
    return Observable.just(Work())
}

class Work
class UserResponse

}

3-还有其他方法吗? 请给我答案,非常感谢!

编辑:,谢谢大家的回答!您的所有答案在实现方式上可能有所不同(使用nested flatMap或使用zip),但是我们都需要将第3类用作我们所需的所有对象的容器类。 内置容器类,我们有:Pair<A, B>Triple<A, B, C> 。如果需要更多的参数,我们必须创建自己的参数

2 个答案:

答案 0 :(得分:1)

您可以使用zip从2个结果中获取一个对象:

public class MergedObject{
    private Work workResponse;
    private UserResponse userResponse;

    MergedObject(final Work workResponse, final UserResponse userResponse){
        this.workResponse= workResponse;
        this.userResponse= userResponse;
    }

    // getter / setter
}

然后

Observable.just("Prepare call API")
    .flatMap {
        apiGetUser()
   }.zipWith(apiGetWork(), ( userResponse, workResponse ) ->
       return new MergedObject(workResponse, userResponse)
   ).subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe { mergedObject->
        Log.e("TAG", "userResponse = " + mergedObject.userResponse)
        Log.e("TAG", "workResponse = " + mergedObject.workResponse)
    }

(未经任何测试编写,可能需要稍作修改)

答案 1 :(得分:1)

您可以使flatmap重载并执行以下操作:

fun test() {
    Observable.just("Prepare call API")
            .flatMap {
                apiGetUser()
            }.flatMap(
                Function<UserResponse, Observable<Work>> {
                    return@Function apiGetWork()
                },
                BiFunction<UserResponse, Work, Pair<UserResponse, Work>> { userResponse, work ->
                    Pair(userResponse, work)
                })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { response ->
                Log.e("TAG", "userResponse = " + response.first.name)
                Log.e("TAG", "workResponse = " + response.second.name)
            }

}

private fun apiGetUser(): Observable<UserResponse> {
    // Fake API to get User
    return Observable.just(UserResponse())
}

private fun apiGetWork(): Observable<Work> {
    // Fake API to get Work
    return Observable.just(Work())
}

class Work {
    val name = "world"
}
class UserResponse {
    val name = "hello"
}

基本上返回Pair<UserResponse, Work> :)