Android 安卓:使用repeatWhen、TakeTill和改型过滤器的rx java无限滚动

Android 安卓:使用repeatWhen、TakeTill和改型过滤器的rx java无限滚动,android,rx-java,retrofit2,rx-android,Android,Rx Java,Retrofit2,Rx Android,我正在使用RxJava对2.2进行改造。 分页的工作原理是这样的:我得到第一批数据,我必须请求第二批数据使用相同的参数,除了一个是最新更新的日期,然后如果我得到空的或同一批数据,这意味着没有更多的项目。我找到了这篇关于如何做的好文章。所以我的代码是: private Observable<Integer> syncDataPoints(final String baseUrl, final String apiKey, final long surveyGroupId

我正在使用RxJava对2.2进行改造。 分页的工作原理是这样的:我得到第一批数据,我必须请求第二批数据使用相同的参数,除了一个是最新更新的日期,然后如果我得到空的或同一批数据,这意味着没有更多的项目。我找到了这篇关于如何做的好文章。所以我的代码是:

private Observable<Integer> syncDataPoints(final String baseUrl, final String apiKey,
        final long surveyGroupId) {
    final List<ApiDataPoint> lastBatch = new ArrayList<>();
    Timber.d("start syncDataPoints");
    return loadAndSave(baseUrl, apiKey, surveyGroupId, lastBatch)
            .repeatWhen(new Func1<Observable<? extends Void>, Observable<?>>() {
                @Override
                public Observable<?> call(final Observable<? extends Void> observable) {
                    Timber.d("Calling repeatWhen");
                    return observable.delay(5, TimeUnit.SECONDS);
                }
            })
            .takeUntil(new Func1<List<ApiDataPoint>, Boolean>() {
                @Override
                public Boolean call(List<ApiDataPoint> apiDataPoints) {
                    boolean done = apiDataPoints.isEmpty();
                    if (done) {
                        Timber.d("takeUntil : finished");
                    } else {
                        Timber.d("takeUntil : will query again");
                    }
                    return done;
                }
            })
            .filter(new Func1<List<ApiDataPoint>, Boolean>() {
                @Override
                public Boolean call(List<ApiDataPoint> apiDataPoints) {
                    boolean unfiltered = apiDataPoints.isEmpty();
                    if (unfiltered) {
                        Timber.d("filtered");
                    } else {
                        Timber.d("not filtered");
                    }
                    return unfiltered;
                }
            }).map(new Func1<List<ApiDataPoint>, Integer>() {
                @Override
                public Integer call(List<ApiDataPoint> apiDataPoints) {
                    Timber.d("Finished polling server");
                    return 0;
                }
            });
}

private Observable<List<ApiDataPoint>> loadAndSave(final String baseUrl, final String apiKey,
        final long surveyGroupId, final List<ApiDataPoint> lastBatch) {
    return loadNewDataPoints(baseUrl, apiKey, surveyGroupId)
            .concatMap(new Func1<ApiLocaleResult, Observable<List<ApiDataPoint>>>() {
                @Override
                public Observable<List<ApiDataPoint>> call(ApiLocaleResult apiLocaleResult) {
                    return saveToDataBase(apiLocaleResult, lastBatch);
                }
            });
}


private Observable<ApiLocaleResult> loadNewDataPoints(final String baseUrl, final String apiKey,
        final long surveyGroupId) {
    Timber.d("loadNewDataPoints");

    return Observable.just(true).concatMap(new Func1<Object, Observable<ApiLocaleResult>>() {
        @Override
        public Observable<ApiLocaleResult> call(Object o) {
            Timber.d("loadNewDataPoints call");
            return restApi
                    .loadNewDataPoints(baseUrl, apiKey, surveyGroupId,
                            getSyncedTime(surveyGroupId));
        }
    });
}
私有可观测syncDataPoints(最终字符串baseUrl、最终字符串apiKey、,
最终长调查组ID){
最终列表lastBatch=newarraylist();
Timber.d(“起始同步数据点”);
返回loadAndSave(baseUrl、apiKey、surveyGroupId、lastBatch)
.repeatWhen(新功能1>(){
@凌驾

公共可观察调用(final Observable因此,我编写了这种API(称为键集分页),并针对它们实现了Rx客户端

这是行为主体有用的情况之一:

S initialState = null;
BehaviorProcessor<T> subject = BehaviorProcessor.createDefault(initialState);
return subject
  .flatMap(state -> getNextElements(state).singleOrError().toFlowable(), Pair::of, 1)
  .serialize()
  .flatMap(stateValuePair -> {
      S state = stateValuePair.getLeft();
      R retrievedValue = stateValuePair.getRight();
      if(isEmpty(retrievedValue)) {
         subject.onComplete();
         return Flowable.empty();
      } else {
         subject.onNext(getNextState(state, retrievedValue));
         return Flowable.just(retrievedValue);
      }
    }
   .doOnUnsubscribe(subject::onCompleted)
   .map(value -> ...)
S initialState=null;
BehaviorProcessor subject=BehaviorProcessor.createDefault(初始状态);
返回主题
.flatMap(state->getNextElements(state).singleOrError().toFlowable(),Pair::of,1)
.serialize()
.flatMap(stateValuePair->{
S state=stateValuePair.getLeft();
R retrievedValue=stateValuePair.getRight();
if(isEmpty(retrievedValue)){
subject.onComplete();
返回Flowable.empty();
}否则{
subject.onNext(getNextState(state,retrievedValue));
返回可流动的.just(retrievedValue);
}
}
.dounsubscribe(主题::未完成)
.map(值->…)
这里

  • getNextElement
    基于状态执行网络调用,并返回一个带有单个值的反应流
  • isEmpty
    确定返回值是否为空,表示元素结束
  • getNextState
    将传入的状态与检索到的值相结合,以确定
    getnextrement
    的下一个状态
如果发生错误(它将被传播),如果您在结束前取消订阅(查询将被终止),它将正常工作


当然,在您的特定情况下,这些不需要是单独的方法或复杂的类型。

感谢我搜索过的有关键集分页的解释,它似乎比偏移要好得多。也感谢我将尝试使用的代码,我还没有使用Flowables。您的意思是什么“这些不需要是单独的方法或复杂类型”?我的意思是代码段更像伪代码-如果(retrievedValue.getList().isEmpty())
,您可以使用f.e
。此外,您也可以使用Observable,但这样会失去反压力。