如何在改型2.0-android中发出多个请求并等待数据来自所有请求

如何在改型2.0-android中发出多个请求并等待数据来自所有请求,android,retrofit2,Android,Retrofit2,当前代码: Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.BASEURL) .addConverterFactory(GsonConverterFactory.create()) .build(); APIService service = retrofit.create(APIService.class);

当前代码:

Retrofit retrofit = new Retrofit.Builder()
                  .baseUrl(Constant.BASEURL)
                  .addConverterFactory(GsonConverterFactory.create())
                  .build();

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

Call<ResponseWrap> call = service.getNewsData();

call.enqueue(new Callback<ResponseWrap>() {

  @Override
  public void onResponse(Call<ResponseWrap> call1, Response<ResponseWrap> response) {
    if (response.isSuccess()) {

        ResponseWrap finalRes = response.body();
        for(int i=0; i<finalRes.getResponse().getResults().size(); ++i){
            String title = finalRes.getResponse().getResults().get(i).getWebTitle();
            News n = new News(titleCategory, title, null);
            newsList.add(n);
        }

        AdapterRecommendation adapter = new AdapterRecommendation(getApplicationContext(), newsList);
        listView.setAdapter(adapter);

    }
    else{
        Toast.makeText(getApplicationContext(), "onResponse  - something wrong" + response.message(), Toast.LENGTH_LONG).show();
    }
  }

  @Override
  public void onFailure(Call<ResponseWrap> call1, Throwable t) {
      Toast.makeText(getApplicationContext(), "exception: " + t.getMessage(), Toast.LENGTH_LONG).show();
  }
});

有谁能帮助我,在改装2.0中,从多个通话中获取数据并等待所有请求都未结束的最佳方式是什么。

您可以通过同步改装通话来实现这一点。为了避免网络异常,我在asynctask内部执行此操作

   List<Something> list = new ArrayList();

public void doInBackground(){
    for(int i = 0; i < numberOfCalls; i++){
        Call<Something> call = service.method1("some_value");
        List<Something> list = call1.execute().body();
        list.add(list1);        
    }
}

public void onPostExecute(){
    AdapterRecommendation adapter = new AdapterRecommendation(getApplicationContext(), newsList);
    listView.setAdapter(adapter);
}
List List=new ArrayList();
公共无效doInBackground(){
for(int i=0;i
这将确保第二次调用仅在第一次调用完成后发生


如果您使用的是RXJava,您可以使用在answer中使用的Zip/flatMap操作符

如果您不介意再添加一个依赖项,您可以使用。 特别是,您应该使用类似以下内容更改服务接口:

@GET("/data")
Observable<ResponseWrap> getNewsData();
@GET(“/data”)
可观察的getNewsData();
现在,您可以执行以下操作:

Observable
            .range(0, **numberOfTimes**, Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnError(new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    Log.e("error", throwable.toString());
                }
            })
            .concatMap(new Func1<Integer, Observable<ResponsWrapper>>() {
                @Override
                public Observable<ResponsWrapper> call(Integer integer) {
                    Log.i("news", "nr:" + integer);
                    //Does the call.
                    return service.getNewsData(integer);
                }
            }).concatMap(new Func1<ResponsWrapper, Observable<News>>() {
        @Override
        public Observable<News> call(final ResponsWrapper responsWrapper) {
            return Observable.fromCallable(new Func0<News>() {
                @Override
                public News call() {
                    //change the result of the call to a news.
                    return new News(responsWrapper.category,responsWrapper.title,null);
                }
            });
        }
    }).toList().subscribe(new Action1<List<News>>() {
        @Override
        public void call(List<News> newList) {
           AdapterRecommendation adapter = new AdapterRecommendation(getApplicationContext(), newsList);
           listView.setAdapter(adapter);
        }
    });
可观察
.range(0,**numberOfTimes**,Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doon错误(新操作1(){
@凌驾
公共无效呼叫(可丢弃可丢弃){
Log.e(“error”,throwable.toString());
}
})
.concatMap(新函数1(){
@凌驾
公共可观察呼叫(整数){
Log.i(“新闻”,“nr:+整数”);
//打电话。
return service.getNewsData(整数);
}
}).concatMap(新函数1(){
@凌驾
公共可观察呼叫(最终应答器){
返回Observable.fromCallable(新的Func0(){
@凌驾
公共新闻电话(){
//将通话结果更改为新闻。
返回新新闻(responswapper.category,responswapper.title,null);
}
});
}
}).toList().subscribe(新操作1()){
@凌驾
公共作废调用(列表新建列表){
AdapterRecommendation adapter=新的AdapterRecommendation(getApplicationContext(),新闻列表);
setAdapter(适配器);
}
});
只要改变几次就行了!希望能有帮助


另外,也许有更干净的方法可以做到这一点。

等待所有请求完成的干净整洁的方法是将改型2与RxJava2及其
zip
功能结合使用

zip
所做的基本上是构造新的observeable,它将等待您的所有改装
observeable
请求完成,然后它将发出自己的结果

下面是一个带有可观察对象的示例2界面:

public interface MyBackendAPI {
  @GET("users/{user}")
  Observable<User> getUser(@Path("user") String user);

  @GET("users/{user}/photos")
  Observable<List<Photo>> listPhotos(@Path("user") String user);

  @GET("users/{user}/friends")
  Observable<List<User>> listFriends(@Path("user") String user);
}

对于任何检查这个问题的人。这对我有用(科特林)

fun-manyRequestsNetworkCall(请求:ArrayList,活动:活动){
可观察的.zip(请求){results->
activity.runOnUiThread(可运行{
//对这些结果做点什么
//runOnUiThread解决了无法在后台线程上执行某些操作的问题
})
//observeOn和subscribeOn解决了NetworkOnMainThreadException的问题
}.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnSubscribe{userWorkdysResponse.value=Response.loading((requestType))}
.订阅({
//当所有的请求都完成时做些什么
},{
//如果出现错误,请采取措施
})
}

我在哪里可以找到可在Reform2中观察到的示例?我非常喜欢这篇文章:我在我的项目中使用Reform和RxJava,我有大约4个API从服务器的4个表中获取数据,并且必须使用ActiveAndroid ORM插入SQLite表中。我想在下载数据时显示进度条,直到数据完成并在本地插入。本地表计数必须等于服务器表计数每个表计数。我还想在每个API响应上按特定顺序调用每个API,然后调用下一个API。应该使用哪些RxJava和翻新库关键字、运算符和过滤器?@hasnain_ahmad如果您找到了解决方案,请在此处共享,因为我也在尝试这样做。感谢使用asynchrounus调用有什么想法?这不是一种很好的实现方法。这基本上是线程内线程。@kridroid no它不是线程内线程。这些是同步调用。所有这些都将发生在同一个线程内。android.os.NetworkOnMainThreadException发生时,您知道吗this@SandunPriyanka是的。检查这个答案:是的,我启用了.zip、.subscribeOn(Schedulers.io()).observeOn(Schedulers.newThread())的两个行为,当它消失后,你的答案节省了我更多的时间。@sandupriyanka我忘了我的答案与改装有关。因此,是的,observeOn/subscribeOn应该可以做到这一点。这里还有另一个答案:@sandupriyanka类似于
instance of
(Java)或
is
(Kotlin)的东西将帮助您识别您接收的对象的类型是否正确。回滚和事务与网络无关。我建议你阅读更多关于反应式编程模式的内容。如果你找到了解决方案,请与我分享。请查看
public interface MyBackendAPI {
  @GET("users/{user}")
  Observable<User> getUser(@Path("user") String user);

  @GET("users/{user}/photos")
  Observable<List<Photo>> listPhotos(@Path("user") String user);

  @GET("users/{user}/friends")
  Observable<List<User>> listFriends(@Path("user") String user);
}
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build();

    MyBackendAPI backendApi = retrofit.create(MyBackendAPI.class);

    List<Observable<?>> requests = new ArrayList<>();

    // Make a collection of all requests you need to call at once, there can be any number of requests, not only 3. You can have 2 or 5, or 100.
    requests.add(backendApi.getUser("someUserId"));
    requests.add(backendApi.listPhotos("someUserId"));
    requests.add(backendApi.listFriends("someUserId"));

    // Zip all requests with the Function, which will receive the results.
    Observable.zip(
            requests,
            new Function<Object[], Object>() {
                @Override
                public Object apply(Object[] objects) throws Exception {
                    // Objects[] is an array of combined results of completed requests

                    // do something with those results and emit new event
                    return new Object();
                }
            })
            // After all requests had been performed the next observer will receive the Object, returned from Function
            .subscribe(
                    // Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
                    new Consumer<Object>() {
                        @Override
                        public void accept(Object o) throws Exception {
                            //Do something on successful completion of all requests
                        }
                    },

                    // Will be triggered if any error during requests will happen
                    new Consumer<Throwable>() {
                        @Override
                        public void accept(Throwable e) throws Exception {
                            //Do something on error completion of requests
                        }
                    }
            );
    val retrofit = Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build()

    val backendApi = retrofit.create(MyBackendAPI::class.java)

    val requests = ArrayList<Observable<*>>()

    requests.add(backendApi.getUser())
    requests.add(backendApi.listPhotos())
    requests.add(backendApi.listFriends())

    Observable
            .zip(requests) {
                // do something with those results and emit new event
                Any() // <-- Here we emit just new empty Object(), but you can emit anything
            }
            // Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
            .subscribe({
                //Do something on successful completion of all requests
            }) {
                //Do something on error completion of requests
            }
fun manyRequestsNetworkCall(requests: ArrayList<Observable<*>>, activity: Activity){
    Observable.zip(requests){results ->
        activity.runOnUiThread(Runnable {
           //do something with those results
           // runOnUiThread solves the problem cannot do something on background thread
        })
      // observeOn and subscribeOn solvesthe problem of NetworkOnMainThreadException
    }.observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.io())
        .doOnSubscribe { userWorkdysResponse.value = Response.loading((requestType)) }
        .subscribe ({
           // do something when all the requests are done
        },{
           // do something if there is an error
        })
}