在RxJava的.flatMap()运算符中处理两种不同的类型

时间:2018-03-28 18:20:20

标签: java rx-java retrofit retrofit2 rx-java2

我正在编写的应用程序使用Retrofit执行初始API调用,该调用返回一个URL。然后,该响应将.flatMap转换为另一个API调用,具体取决于URL中包含的文本。但是,定义了两个辅助API调用以返回不同的响应模型。

为了使事情更清楚,这里有一些代码:

APIService service = retrofit.create(APIService.class);

service.getURL() // returns response model containing a URL.                                                                                                                                                                                  
.flatMap(new Function<GetURLResponse, ObservableSource<?>>() {                                                       
    @Override                                                                                                            
    public ObservableSource<?> apply(GetURLResponse getURLResponse) throws Exception {                           

        // Determine whether the returned url is for "first.com".                                       
        if (getURLResponse.url.contains("first.com")) {                                    
            return service.first(getURLResponse.url);                                                                                   
        }                                                                                                                

        // Otherwise, the URL is not for "first.com", so use our other service method.                                                         
        return service.second(getURLResponse.url);                                    
    }                                                                                                                    
})

以下是service.first()service.second()的接口定义:

@GET                                                                                    
Observable<retrofit2.Response<ResponseBody>> first(@Url String url);                    

@GET                                                                                    
Observable<SecondModel> second(@Url String url);  

如何为流的其余部分更好地处理这两种不同的可能类型(retrofit2.Response<ResponseBody>SecondModel)?例如。如果初始网址包含first.com,则应触发service.first() API调用,并且流中的运营商应收到retrofit2.Response<ResponseBody>。相反,如果初始网址包含first.com,则应启动service.second() API调用,并且流中的运营商应收到SecondModel

1 个答案:

答案 0 :(得分:2)

最简单的方法是让你的模型类实现一个接口并返回该接口,或者模型可以扩展一个抽象类来实现相同的效果。然后,您将进行instanceOf检查以查看它是哪个模型并继续您的首选转换。

那说你提到下游运营商,让我觉得这会导致烦人的支票数量。所以我要做的是使用publish运算符拆分流,然后将进一步的转换应用于每个子流。最后,您应该将两个流合并在一起并返回包含两个模型的单个模型。

下面的代码示例,以帮助您入门。

Observable<Integer> fooObservableSecondaryRequest(String foo) {
    return Observable.just(1);
}
Observable<Integer> booObservableSecondaryRequest(String boo) {
    return Observable.just(2);
}
Observable<String> stringObservable = Observable.just("foo", "boo");

stringObservable.publish(shared -> Observable.merge(
            shared.filter(a -> a.equals("foo"))
                    .flatMap(fooString -> fooObservableSecondaryRequest(fooString))
                    .map(num -> num * 2),
            shared.filter(a -> a.equals("boo"))
                    .flatMap(booString -> booObservableSecondaryRequest(booString))
                    .map(num -> num * 10)
    )).subscribe(result -> System.out.println(result)); // will print 2 and 20