Retrofit和RxJava:如何组合两个请求并获得对这两个结果的访问权限? [英] Retrofit and RxJava: How to combine two requests and get access to both results?

查看:224
本文介绍了Retrofit和RxJava:如何组合两个请求并获得对这两个结果的访问权限?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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>类型= 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(流派,电影,新Func2< GenerosResponse,ResponseMovies,CollectionsMovies>(){
@Override
public CollectionsMovies call(GenerosResponse generosResponse,ResponseMovies responseMovies){
return new CollectionsMovies (generosResponse,responseMovies);
}
});

合计。
subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...);

修改



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

  private Observable< GenerosResponse> makeRequestToServiceA(){
return service.getAllGeneros(movie,list,da0d692f7f62a1dc687580f79dc1e6a0); //一些网络电话
}

private Observable< ResponseMovies> makeRequestToServiceB(流派类型){
返回service.getAllMovies(genre.getId(),movies,da0d692f7f62a1dc687580f79dc1e6a0,created_at.asc); //基于ServiceA的响应的一些网络调用
}

void doTheJob(){

makeRequestToServiceA()
.flatMap(userResponse - > Observable.just(userResponse.getGenres()))//从响应中获取列表
.flatMapIterable(baseDatas - > baseDatas)
.flatMap(new Func1< Genre,Observable<?extends ResponseMovies>> (){

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

@Override
public CollectionsMovies call(流派类型,ResponseMovies responseMovies){
返回新的CollectionsMovies(流派,responseMovies) ;
}
})。
subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(....);
}


解决方案

据我所知 - 你需要根据另一个请求的结果发出请求并合并两个结果。为此,您可以使用此 flatMap 运算符变体:


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

  private Observable< String> makeRequestToServiceA(){
return Observable.just(serviceA response); //一些网络电话
}

private Observable< String> makeRequestToServiceB(String serviceAResponse){
return Observable.just(serviceB response); //基于ServiceA的响应的一些网络调用
}

private void doTheJob(){
makeRequestToServiceA()
.flatMap(new Func1< String,Observable< ?extends String>>(){
@Override
public Observable<?extends String> call(String responseFromServiceA){
//根据ServiceA的响应发出第二个请求
返回makeRequestToServiceB(responseFromServiceA);
}
},new Func2< String,String,Observable< String>>(){
@Override
public Observable< String> call( String responseFromServiceA,String responseFromServiceB){
//合并结果
返回Observable.just(这里是合并结果!);
}
})
//应用调度程序,订阅等
}

使用lambdas:

  private void doTheJob(){
makeRequestToServiceA( )
.flatMap(responseFromServiceA - > makeRequestToServiceB(responseFromServiceA),
(responseFromServiceA,responseFromServiceB) - > Observable.just(这里是合并结果!))
// ... ...
}


I need to make two requests for services and combine it results:

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

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

Currently, I have managed to combine the results, but I need to pass id as a parameter to the ServiceB and get access to the first result.

What I tried so far:

   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(...);

Edit

Solution according to @Maxim Ostrovidov's answer:

 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(....);
    }

解决方案

As I understand - you need to make a request based on result of another request and combine both results. For that purpose you can use this flatMap operator variant: Observable.flatMap(Func1 collectionSelector, Func2 resultSelector)

Returns an Observable that emits the results of a specified function to the pair of values emitted by the source Observable and a specified collection Observable.

Simple example to point you how to rewrite your code:

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
}

Using lambdas:

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

这篇关于Retrofit和RxJava:如何组合两个请求并获得对这两个结果的访问权限?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆