我希望从可观察的结果中获得10次结果,如果是错误或成功则无关紧要。这是我正在尝试的
mPortalNetworkService.getApi()
.login(mUsername, mPassword, mEmail)
.repeat(10)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
println("Finally here -> SUB")
println(it)
}, {
println("Finally here -> Error")
it.printStackTrace()
})
我正在调用一个用于记录的rest api(使用Retrofit)。我面临的问题是它只返回一次结果。我想要运行这个可观察的所有10
次的结果。我该怎么做?
答案 0 :(得分:2)
不幸的是,没有运营商可以将repeat
和retry
行为结合起来。您可以设置Hans建议的基于range
的解决方案,也可以在repeat
和retry
之间共享一个计数器来限制两者:
static <T> ObservableTransformer<T, T> redo(int maxCount) {
return o -> {
Observable.defer(() -> {
AtomicInteger count = new AtomicInteger(maxCount);
return o.repeat(() -> count.incrementAndGet() < maxCount)
.retry(err -> count.incrementAndGet() < maxCount);
});
};
}
mPortalNetworkService.getApi()
.login(mUsername, mPassword, mEmail)
.subscribeOn(Schedulers.io())
.compose(redo(10))
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
println("Finally here -> SUB")
println(it)
}, {
println("Finally here -> Error")
it.printStackTrace()
})
请注意,要确保后台线程上发生login
,您必须在重复/重试之前subscribeOn
。
答案 1 :(得分:1)
为了创建10个请求,您只需使用#range来生成10个值,并将每个值映射到新请求。每个请求都将使用maxConcurrency = 1进行平面映射。您还可以使用concatMap在请求完成之后发出请求。
@Test
public void name() {
Api api = mock(Api.class);
when(api.login()).thenReturn(Flowable.just(42));
TestScheduler testScheduler = new TestScheduler();
Flowable<Result> resultFlowable =
Flowable.range(0, 10)
.flatMap(
__ -> {
Flowable<Result> resultObservable =
api.login()
.map(integer -> Result.ok())
.timeout(10, TimeUnit.SECONDS, testScheduler)
.onErrorReturn(throwable -> Result.fail());
return resultObservable;
},
1);
TestSubscriber<Result> test = resultFlowable.test();
testScheduler.advanceTimeBy(1, TimeUnit.HOURS);
test.assertValueCount(10) //
.assertNoErrors()
.assertComplete();
}
interface Api {
Flowable<Integer> login();
}
static class Result {
private Result() {}
static Result ok() {
return new Result();
}
static Result fail() {
return new Result();
}
}