如何使用Retrofit2/RxJava2合并多请求返回列表以设置RecyclerView适配器
问题原因
- 注释
subscribeOn(Schedulers.io())无回调的原因:你没有实现错误回调逻辑,发生异常时不会有任何提示。RxJava中不指定订阅线程时,若当前线程为主线程,Retrofit的网络请求会直接抛出「主线程不能访问网络」的异常,被你空实现的Consumer<Throwable>吃掉,所以不会走到PLACE1和PLACE2。 - 开启异步后无法操作列表的原因有两个:
- 你设置了
observeOn(Schedulers.newThread()),回调逻辑运行在子线程,安卓不允许在子线程操作UI,所以设置RecyclerView适配器会直接崩溃,同样被空错误回调吃掉无提示 - 网络请求是异步逻辑,你在
subscribe之后直接打印外部列表ar、尝试返回ar的时候,请求还没有完成,列表自然是空的,异步逻辑不能用同步返回的方式获取结果。
- 你设置了
解决方案
- 先确保引入RxAndroid依赖,获取主线程调度器(安卓环境必要)
- 修正线程配置,保留IO线程订阅,回调切到主线程
- 补全错误回调逻辑,方便排查问题
- 所有对请求结果的操作(设置适配器、数据存储等)都放在subscribe的成功回调中执行,不要尝试同步返回列表;如果需要在其他地方使用这个列表,可以定义接口回调,在成功回调中把列表传递出去即可。
修正后的代码
private void getListArticles(List<Integer> l) { Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseURL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); ApiInterface apiInterface = retrofit.create(ApiInterface.class); List<Observable<Articles>> requests = new ArrayList<>(); for(int id: l){ requests.add(apiInterface.getArticle1(id)); } Observable.zip(requests, new Function<Object[], List<Articles>>() { @Override public List<Articles> apply(@NonNull Object[] objects) throws Exception { // PLACE 1. List<Articles> articlesArrayList = new ArrayList<>(); for (Object response : objects) { articlesArrayList.add((Articles) response); } return articlesArrayList; } }) .subscribeOn(Schedulers.io()) // 保留异步配置,请求在IO线程执行 .observeOn(AndroidSchedulers.mainThread()) // 回调切到主线程,可直接操作UI .subscribe( new Consumer<List<Articles>>() { @Override public void accept(List<Articles> articlesList) throws Exception { // PLACE 2. // 这里直接操作结果即可,不需要再存到外部的临时列表 recycleView.setAdapter(new Adapter(articlesList, getApplicationContext())); } }, new Consumer<Throwable>() { @Override public void accept(Throwable e) throws Exception { // 补全错误日志,出问题可以直接看报错 e.printStackTrace(); } } ); }
内容的提问来源于stack exchange,提问作者Patryk
相关产品推荐
相关产品推荐

