RXJava Android - 创建另一个可观察对象所需的可观察结果
RXJava Android - Observable result needed to create another observable
我找不到一种方法来组合或链接一系列可观察对象,它的响应是创建另一个可观察对象的其他调用的先决条件。
我正在对可观察对象进行改造。
我的服务:
String url = "/geocode/json?sensor=false";
@GET(url)
Observable<GeocodeResult> getReverse(@Query("key") String gMapsKey,
@Query("latlng") LatLng origin);
另一个服务需要 GeocodeResult
@POST("/api/orders")
Observable<Order> createOrder(@Body GeocodeResult newOrder);
我正在尝试:
// 先决条件 1
可观察地理编码Observable = Address.get(...);
// 获取geocode后调用createOrder?
return Observable.combineLatest(geocodeObservable, geocode -> createOrder(geocode));
但它不起作用,因为 combineLatest 需要一个对象,而不是一个可观察对象,但我需要 return 可观察对象。
使用 JoinObservable:
Pattern5<Geocode> pattern = JoinObservable.from(geocodeObservable)
Plan0<Observable<Order>> plan = pattern.then(Order::create);
return JoinObservable.when(plan).toObservable().toBlocking().single();
但是它抛出一个NoSuchElementException异常。为什么?
我做 toBlocking().single()
因为我需要 Observable 而不是 Observable<Observable<Order>>
:(.
或者我该怎么做?
您可以尝试使用 flatMap,它可以将第二个可观察值作为参数。
该函数获取第一个 observable 发出的项目并为每个项目创建一个 observable,然后将这些 observable 发出的项目扁平化为单个 observable。这听起来很复杂,但幸运的是,您的两个 Retrofit 函数都只发出一个项目,因此只有一个可观察对象 "flattened" 变成可观察对象。
您可以这样使用 flatMap
:
restApi.getReverse(gMapsKey, origin)
.flatMap(geocodeResult -> createOrder(geocodeResult))
.subscribe(order -> doSomething(order));
combineLatest
并不真正符合您的需求,因为它会同时执行两个 REST 调用,而不是一个接一个地执行,因此您不能将第一个的响应用作第二个参数。我无法评论为什么 JoinObservable
会抛出异常,因为它不是任何 public API 的一部分。此外 toBlocking()
不应该用于测试以外的任何用途。
我最终创建了一个新对象,并使用 Observable.combineLatest
结合创建新 Observable 的所有先决条件,然后使用 flatMap 从该 observable 创建新 Observable。
Observable<NewOrderWrapper> newOrderObservable = Observable.combineLatest(prerequisites, (param1, param2,...) -> {return new NewOrderWrapper(param1, param2,...)});
然后
Observable<Order> finalOrderObservable = newOrderObservable.flatMap(newOrderWrapper -> create(newOrderWrapper))
在这里勾选一个 post MakinGIANST/RXJava post。
感谢@LukaCiko
我找不到一种方法来组合或链接一系列可观察对象,它的响应是创建另一个可观察对象的其他调用的先决条件。
我正在对可观察对象进行改造。
我的服务:
String url = "/geocode/json?sensor=false";
@GET(url)
Observable<GeocodeResult> getReverse(@Query("key") String gMapsKey,
@Query("latlng") LatLng origin);
另一个服务需要 GeocodeResult
@POST("/api/orders")
Observable<Order> createOrder(@Body GeocodeResult newOrder);
我正在尝试:
// 先决条件 1 可观察地理编码Observable = Address.get(...);
// 获取geocode后调用createOrder? return Observable.combineLatest(geocodeObservable, geocode -> createOrder(geocode));
但它不起作用,因为 combineLatest 需要一个对象,而不是一个可观察对象,但我需要 return 可观察对象。
使用 JoinObservable:
Pattern5<Geocode> pattern = JoinObservable.from(geocodeObservable)
Plan0<Observable<Order>> plan = pattern.then(Order::create);
return JoinObservable.when(plan).toObservable().toBlocking().single();
但是它抛出一个NoSuchElementException异常。为什么?
我做 toBlocking().single()
因为我需要 Observable 而不是 Observable<Observable<Order>>
:(.
或者我该怎么做?
您可以尝试使用 flatMap,它可以将第二个可观察值作为参数。
该函数获取第一个 observable 发出的项目并为每个项目创建一个 observable,然后将这些 observable 发出的项目扁平化为单个 observable。这听起来很复杂,但幸运的是,您的两个 Retrofit 函数都只发出一个项目,因此只有一个可观察对象 "flattened" 变成可观察对象。
您可以这样使用 flatMap
:
restApi.getReverse(gMapsKey, origin)
.flatMap(geocodeResult -> createOrder(geocodeResult))
.subscribe(order -> doSomething(order));
combineLatest
并不真正符合您的需求,因为它会同时执行两个 REST 调用,而不是一个接一个地执行,因此您不能将第一个的响应用作第二个参数。我无法评论为什么 JoinObservable
会抛出异常,因为它不是任何 public API 的一部分。此外 toBlocking()
不应该用于测试以外的任何用途。
我最终创建了一个新对象,并使用 Observable.combineLatest
结合创建新 Observable 的所有先决条件,然后使用 flatMap 从该 observable 创建新 Observable。
Observable<NewOrderWrapper> newOrderObservable = Observable.combineLatest(prerequisites, (param1, param2,...) -> {return new NewOrderWrapper(param1, param2,...)});
然后
Observable<Order> finalOrderObservable = newOrderObservable.flatMap(newOrderWrapper -> create(newOrderWrapper))
在这里勾选一个 post MakinGIANST/RXJava post。
感谢@LukaCiko