改造与改造RxJava多个请求完成

时间:2017-04-18 09:09:27

标签: android retrofit rx-java

我需要这样做:

  1. 请求2个来自不同网站的新闻列表
  2. 合并请求的结果
  3. 按日期对项目进行排序
  4. 获取10条最新消息
  5. 保存他们
  6. 显示完整的消息
  7. 例如,我有两个可观测量:

    Observable<RegionalNews> regionalNews;
    Observable<NationalNews> nationalNews;
    
    public interface NewsNationalService {
      @GET("news/national")
      Observable<News> getNationalNews();
    }
    
    public interface NewsRegionalService {
      @GET("news/regional")
      Observable<News> getRegionalNews();
    }
    

4 个答案:

答案 0 :(得分:7)

您可以使用zip运算符调用2个异步请求,并在响应时保存或处理其数据。

例如。

以下是两个Observable

Observable<ResponseOne> responseOneObservable = getRetrofitClient().getDataOne()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());

Observable<ResponseTwo> responseTwoObservable = getRetrofitClient().getDataTwo()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());

在上面两个zip上使用Observable运算符,如下所示。

Observable<ArrayList<TestData>> testDataObservable = Observable.zip(responseOneObservable, responseTwoObservable, new Func2<ResponseOne, ResponseTwo, ArrayList<TestData>>() {
            @Override
                public ArrayList<TestData> call(ResponseOne responseOne, ResponseTwo responseTwo) {
                  ArrayList<TestData> testDataList = new ArrayList();
                      // process data from response responseOne & responseTwo
                  return testDataList;
            } 
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Subscriber<ArrayList<TestData>>() {

        @Override
        public void onNext(ArrayList<TestData> testDataList) {

        }

        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted" ); 
            // you can show alert here or do something when completed 
        }

        @Override
        public void onError(Throwable t) {
            Log.d(TAG, "onError Throwable: " + t.toString() );
        }
    });

答案 1 :(得分:4)

一如既往,这取决于它。您是否需要在链中处理返回的值,或者只保存它?

在此实现中,我使用Single和Completable。您订阅了完成表,当两个单曲结束时您将收到通知。

@Test
public void name() throws Exception {
        TestScheduler testScheduler = new TestScheduler();
        Single<Long> request1 = Single.timer(1000, TimeUnit.MILLISECONDS, testScheduler)
                .doOnSuccess(aLong -> {
                    System.out.println("save to db.");
                });
        Single<Long> request2 = Single.timer(500, TimeUnit.MILLISECONDS, testScheduler)
                .doOnSuccess(aLong -> {
                    System.out.println("save to db.");
                });

        Completable completable = Single.zip(request1, request2, (aLong, aLong2) -> aLong).toCompletable();

        TestObserver<Void> test = completable.test();

        testScheduler.advanceTimeBy(1010, TimeUnit.MILLISECONDS);

        test.assertComplete();
}

您也可以使用flatMapCompletable而不是doOnSuccess

@Test
public void name() throws Exception {
    TestScheduler testScheduler = new TestScheduler();
    Completable request1 = Single.timer(1000, TimeUnit.MILLISECONDS, testScheduler)
            .flatMapCompletable(this::saveToDb);

    Completable request2 = Single.timer(500, TimeUnit.MILLISECONDS, testScheduler)
            .flatMapCompletable(this::saveToDb);

    // need to cheat here, becuase completeable does not provide zip
    Completable completable = Single.zip(request1.toSingle(() -> 1), request1.toSingle(() -> 1), (aLong, aLong2) -> aLong)
            .toCompletable();

    TestObserver<Void> test = completable.test();

    testScheduler.advanceTimeBy(1010, TimeUnit.MILLISECONDS);

    test.assertComplete();
}

private Completable saveToDb(long value) {
    return Completable.complete();
}

答案 2 :(得分:4)

如果您不想对组合结果执行特定操作,则merge()就足够了:

Observable<RegionalNews> regionalNews = ...;
Observable<NationalNews> nationalNews = ...;

Observable
.merge(regionalNews, nationalNews)
.ignoreElements()
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete(() -> { /* show alert */ })
.subscribe()

答案 3 :(得分:3)

zip是组合observables的方法。结合他们的结果只是一个结果。

如果您想等待两个observable完成(完成),最简单的方法是使用zip。您只需在合并功能中不必使用请求的结果即可。只需使用此函数作为在这两个调用完成时发出不同内容的方法。当此功能发出项目时:

  

[...]在所有请求完成后执行某些操作(例如显示警告)

例如像这样(当两个请求完成时执行someOtherCall):

Observable<Integer> obs1 = ...;
Observable<Long> obs2 = ...;

Observable.zip(obs1, obs2, new Func2<Integer, Long, String>() {
    @Override
    public String call(Integer integer, Long aLong) {
        return "something completely different";
    }
}).flatMap(new Func1<String, Observable<Float>>() {
    @Override
    public Observable<Float> call(String s) {
        return performSomeOtherCall();
    }
}).subscribe(...);