Android 当组合两个可观测流时,如何发出最终值?
使用杰克·沃顿的模式 我将两个api调用组合在一起并行执行 当两者都已完成时,如何发出“成功”项 请参阅下面代码中的注释 谢谢 主调用函数:Android 当组合两个可观测流时,如何发出最终值?,android,kotlin,rx-java,Android,Kotlin,Rx Java,使用杰克·沃顿的模式 我将两个api调用组合在一起并行执行 当两者都已完成时,如何发出“成功”项 请参阅下面代码中的注释 谢谢 主调用函数: Observable .just(UpdatePicEvent(userId, file)) .compose(updatePic()) <-- Handles updating pic, emits models consumed by UI .mergeWith(
Observable
.just(UpdatePicEvent(userId, file))
.compose(updatePic()) <-- Handles updating pic, emits models consumed by UI
.mergeWith(
Observable
.just(UpdateProfileEvent(..params...))
.compose(updateProfile()) <-- Handles updating other settings, emits models consumed by UI
)
// TODO Need to add something to emit a Success() model item when both actions above have completed
.subscribe(...pass models to UI...)
可观察
.just(更新事件(用户ID、文件))
.compose(updateepic())您将收到两个不同的profilesetingsModel
您需要合并。如果您不想在订阅者中执行此操作,您也可以使用一个
通过指定函数将多个观测值的发射组合在一起,并根据该函数的结果为每个组合发射单个项目
其中,mergePicAndProfile
是一个双功能
接收结果并发出单个实体。根据您对原始问题的评论,可以帮助您。文件的相关部分说:
Concat操作符将多个可观察对象的输出连接起来,使它们的行为类似于单个可观察对象,第一个可观察对象发出的所有项目在第二个可观察对象发出的任何项目之前发出(如果有两个以上的项目,则依此类推)
Concat等待订阅您传递给它的每个附加可观察对象,直到前一个可观察对象完成
实施:
这项工作有两个关键因素:
您需要替换updateProfile
和updateProfile
转换器中的onerrorrenue
,以便它们在失败时实际发出错误(可能是类似onerrorrumerenext{Observable.error(MyTypeOfException())}
。如果不这样做,流将无法知道是否存在错误(因为将错误包装到项目中会使其无法与成功区分)
使用mergeDelayError
让每个流独立于另一个流继续。如果只使用merge
,第一个失败的流将阻止另一个流继续
(请注意,我稍微修改了您的原始代码,以使其更具可读性)您最终的成功需要从结果中得到什么吗?您试图通过最后发出的东西实现什么?此外,您是否需要按顺序调用updateProfile
和updateProfile
(看起来你不需要,因为你合并了……但要确保给你一个好的答案)@marianosimone“你最终的成功需要结果吗?”在这种情况下,不需要。“你想通过你最后发出的东西实现什么?”我正在使用密封类ProfileSettingsModel
来传递事务的状态。我要发出的最后一件事是表示两个API调用都已成功完成。谢谢!有任何答案可以解决您的问题吗?这在两个调用成功时起作用(感谢改进的语法)。但是,当出现错误时,它仍会发出“AllSuccessful”。哦,我没有意识到您正在将错误包装到转换器内的实际结果中。请查看我的编辑以了解这是否有助于感谢您的帮助。但是,转换器在其他地方作为单独调用使用,因此更改它们有点达不到目的。我正在查找或者是一种不必编写新链就可以将它们组合起来的方法。似乎我应该只携带成功排放的状态,并在订阅
中检查它们?我想是的。如果您将错误封装在排放中,那么您将无法区分整体成功和失败,除非您以某种方式检查它们在订阅中。
fun updatePic(): ObservableTransformer<UpdatePicEvent, ProfileSettingsModel> {
return ObservableTransformer {
it.flatMap {
api.uploadProfilePic(it.userId, it.pic)
.map { UpdatePicSuccessful(it) as ProfileSettingsModel }
.onErrorReturn { UpdatePicError(it) as ProfileSettingsModel }
.startWith(UpdatePicInProgress() as ProfileSettingsModel)
}
}
}
fun updateProfile(): ObservableTransformer<UpdateProfileEvent, ProfileSettingsModel> {
return ObservableTransformer {
it.flatMap {
api
.updateUser(...params...)
.subscribeOn(Schedulers.io())
.map { UpdateProfileSuccessful(it) as ProfileSettingsModel }
.onErrorReturn { UpdateProfileError(it) as ProfileSettingsModel }
.observeOn(AndroidSchedulers.mainThread())
.startWith(UpdateProfileInProgress() as ProfileSettingsModel)
}
}
}
Observable.zip(
Observable.just(UpdatePicEvent(userId, file)).compose(updatePic())
Observable.just(UpdateProfileEvent(..params...)).compose(updateProfile())
mergePicAndProfile)
Observable.mergeDelayError(
Observable.just(UpdatePicEvent(userId, file)).compose(updatePic()),
Observable.just(UpdateProfileEvent(userId, params)).compose(updateProfile())
)
.concatWith(Observable.just(AllSuccessful())) // Or whatever
.onErrorReturn { when (it) {
is UpdatePicException -> UpdatePicError(it)
is UpdateProfileException -> UpdateProfileError(it)
}}