Retrofit和RxJava:如何组合两个请求并访问这两个结果?

时间:2017-01-22 01:33:56

标签: java android rx-java retrofit2

我需要提出两项服务请求并将其结合起来:

ServiceA()=> [{"id":1,"name":"title"},{"id":1,"name":"title"}]

ServiceB(id)=> {"field":"value","field1":"value"}

目前,我已设法合并结果,但我需要将id作为参数传递给 ServiceB ,并获取对第一个结果的访问权限。

到目前为止我尝试了什么:

   Retrofit repo = new Retrofit.Builder()
                .baseUrl("https://api.themoviedb.org/3/genre/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        Observable<GenerosResponse> Genres  = repo
                .create(services.class)
                .getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0")
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread());

        Observable<ResponseMovies> Movies = repo
                .create(services.class)
                .getAllMovies("28","movies","da0d692f7f62a1dc687580f79dc1e6a0",12)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread());

        Observable<CollectionsMovies> combined = Observable.zip(Genres, Movies, new Func2<GenerosResponse, ResponseMovies, CollectionsMovies>() {
            @Override
            public CollectionsMovies call(GenerosResponse generosResponse, ResponseMovies responseMovies) {
                return new CollectionsMovies(generosResponse, responseMovies);
            }
        });

        combined.
                subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(...);

修改

解决方案根据@Maxim Ostrovidov的回答:

 private Observable<GenerosResponse> makeRequestToServiceA() {
        return  service.getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0"); //some network call
    }

    private Observable<ResponseMovies> makeRequestToServiceB(Genre genre) {
        return service.getAllMovies(genre.getId(),"movies","da0d692f7f62a1dc687580f79dc1e6a0","created_at.asc"); //some network call based on response from ServiceA
    }

    void doTheJob() {

        makeRequestToServiceA()
        .flatMap(userResponse -> Observable.just(userResponse.getGenres()))      //get list from response
                .flatMapIterable(baseDatas -> baseDatas)
                .flatMap(new Func1<Genre, Observable<? extends ResponseMovies>>() {

                    @Override
                    public Observable<? extends ResponseMovies> call(Genre genre) {
                        return makeRequestToServiceB(genre);
                    }
                }, new Func2<Genre, ResponseMovies, CollectionsMovies>() {

                    @Override
                    public CollectionsMovies call(Genre genre, ResponseMovies responseMovies) {
                        return new CollectionsMovies(genre,responseMovies);
                    }
                }).
                subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(....);
    }

2 个答案:

答案 0 :(得分:27)

据我了解 - 您需要根据其他请求的结果发出请求并合并两个结果。为此,您可以使用此flatMap运算符变体:Observable.flatMap(Func1 collectionSelector, Func2 resultSelector)

  

返回一个Observable,它将指定函数的结果发送到源Observable和指定集合Observable发出的值对。enter image description here

简单示例指出如何重写代码:

private Observable<String> makeRequestToServiceA() {
    return Observable.just("serviceA response"); //some network call
}

private Observable<String> makeRequestToServiceB(String serviceAResponse) {
    return Observable.just("serviceB response"); //some network call based on response from ServiceA
}

private void doTheJob() {
    makeRequestToServiceA()
            .flatMap(new Func1<String, Observable<? extends String>>() {
                @Override
                public Observable<? extends String> call(String responseFromServiceA) {
                    //make second request based on response from ServiceA
                    return makeRequestToServiceB(responseFromServiceA);
                }
            }, new Func2<String, String, Observable<String>>() {
                @Override
                public Observable<String> call(String responseFromServiceA, String responseFromServiceB) {
                    //combine results
                    return Observable.just("here is combined result!");
                }
            })
            //apply schedulers, subscribe etc
}

使用lambdas:

private void doTheJob() {
    makeRequestToServiceA()
            .flatMap(responseFromServiceA -> makeRequestToServiceB(responseFromServiceA),
                    (responseFromServiceA, responseFromServiceB) -> Observable.just("here is combined result!"))
            //...
}

答案 1 :(得分:2)

您正在寻找的运营商是flatMap()

serviceA.getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0")
    .flatMap(genres -> serviceB.getAllMovies(genres.getId() ......))