如何从 Observable 获取多种数据类型,因为仅接受 Observable<T> 的一种通用类型
How to get multiple data type from Observable since only one generic type from Observable<T> accepted
我们已经知道 Observable 的泛型类型只能有一个参数。可观察的
我假设我有 2 个网络调用,其中 return 2 个数据类型:UserResponse
和 WorkResponse
。
我想一步一步地调用 2 这些 APIs,getUser 然后 getWork。
最后我订阅了他们,得到的只有一种数据类型,显然是WorkResponse
,因为getWork是上游Observable<WorkResponse>
最后一个API调用。
但是在订阅代码块中,我想同时获得 UserResponse
和 WorkResponse
。那么我该如何实现呢?
1 - 有人说我应该创建一个容器 class 来包含 UserResponse
和 WorkResponse
然后我可以在订阅代码块中从那个容器中获取这些数据类型。
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
),但我们都需要使用第三个 class 作为所有容器 class我们需要的对象。
内置容器 classes,我们有:Pair<A, B>
和 Triple<A, B, C>
.如果我们需要更多参数,我们必须创建自己的参数
您可以使用 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)
}
(未经任何测试编写,您可能需要稍微适应一下)
您可以重载 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>
:)
我们已经知道 Observable 的泛型类型只能有一个参数。可观察的
我假设我有 2 个网络调用,其中 return 2 个数据类型:UserResponse
和 WorkResponse
。
我想一步一步地调用 2 这些 APIs,getUser 然后 getWork。
最后我订阅了他们,得到的只有一种数据类型,显然是WorkResponse
,因为getWork是上游Observable<WorkResponse>
最后一个API调用。
但是在订阅代码块中,我想同时获得 UserResponse
和 WorkResponse
。那么我该如何实现呢?
1 - 有人说我应该创建一个容器 class 来包含 UserResponse
和 WorkResponse
然后我可以在订阅代码块中从那个容器中获取这些数据类型。
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
),但我们都需要使用第三个 class 作为所有容器 class我们需要的对象。
内置容器 classes,我们有:Pair<A, B>
和 Triple<A, B, C>
.如果我们需要更多参数,我们必须创建自己的参数
您可以使用 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)
}
(未经任何测试编写,您可能需要稍微适应一下)
您可以重载 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>
:)