假设我有List<CharSequence> observableList
,其中包含长度为1到10的随机CharSequence
。
我有Observable
:
Observable.from(observableList)
.flatMap(new Func1<CharSequence, Observable<CharSequence>>() {
@Override
public Observable<CharSequence> call(CharSequence charSequence) {
if (charSequence.length() == 1) {
return Observable.error(new RuntimeException("Too short"));
} else {
return Observable.just(charSequence);
}
}
}).retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
@Override
public Observable<?> call(final Observable<? extends Throwable> observable) {
return observable.flatMap(new Func1<Throwable, Observable<?>>() {
@Override
public Observable<?> call(Throwable throwable) {
if (backoffStrategy.isApplicable(throwable)) {
Log.d(MainActivity.class.getSimpleName(), "Appropriate throwable is thrown!");
return backoffStrategy.call(observable);
}
return observable;
}
});
}
})
当序列长度为1时,observable抛出异常。在retryWhen
&#39; s Func1
内我想检查错误类型(RuntimeException
只是一个例子)并且选择适当的重试策略。
这是退避策略:
public class BaseBackoffStrategy implements BackoffStrategy {
@Override
public Observable<?> call(Observable<? extends Throwable> attempts) {
return attempts.zipWith(Observable.range(1, 3 + 1), new ObservableUtils.RxPair<Throwable, Integer>())
.flatMap(new Func1<Pair<Throwable, Integer>, Observable<?>>() {
@Override
public Observable<?> call(Pair<Throwable, Integer> ti) {
if (ti.second <= 3) {
System.out.println(new Date().toGMTString() + " : " + ti.second + " retry");
return Observable.timer((long) Math.pow(2, ti.second), TimeUnit.SECONDS);
} else {
return Observable.error(ti.first);
}
}
});
}
@Override
public boolean isApplicable(Throwable throwable) {
return RuntimeException.class.isInstance(throwable);
}
}
private interface BackoffStrategy extends Func1<Observable<? extends Throwable>, Observable<?>> {
boolean isApplicable(Throwable throwable);
}
该函数只返回Pair
个对象:
public class ObservableUtils {
public static class RxPair<T1, T2> implements Func2<T1, T2, Pair<T1, T2>> {
@Override
public Pair<T1, T2> call(T1 t1, T2 t2) {
return Pair.of(t1, t2);
}
}
}
来自控制台的输出是:
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:34 GMT : 1 retry
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:36 GMT : 1 retry
I/System.out: 6 Oct 2016 07:34:36 GMT : 2 retry
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:38 GMT : 1 retry
I/System.out: 6 Oct 2016 07:34:38 GMT : 3 retry
I/System.out: 6 Oct 2016 07:34:38 GMT : 2 retry
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:40 GMT : 1 retry
I/System.out: 6 Oct 2016 07:34:40 GMT : 3 retry
I/System.out: 6 Oct 2016 07:34:40 GMT : 2 retry
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:40 GMT : 1 retry
I/System.out: 6 Oct 2016 07:34:40 GMT : 3 retry
I/System.out: 6 Oct 2016 07:34:40 GMT : 2 retry
D/MainActivity: onError
但我希望Observable
在指定时间后重试。抛出下一个异常时,时间应该变长。控制台的输出应如下所示:
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:34 GMT : 1 retry
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:36 GMT : 2 retry
D/MainActivity: Appropriate throwable is thrown!
I/System.out: 6 Oct 2016 07:34:38 GMT : 3 retry
D/MainActivity: Appropriate throwable is thrown!
D/MainActivity: onError
我的问题是:我在这里做错了什么?我可以从
Func1
致电其他Func1
吗?
答案 0 :(得分:2)
使用RxJava时,最好使用lamdas而不是内部类。您的代码变得更具可读性。
我认为你在这里犯了一个错误return backoffStrategy.call(observable);
每当retryWhen
发出异常时,您都会重新创建zip +计时器。这就是为什么你有单,双,三等消息,如
I/System.out: 6 Oct 2016 07:34:40 GMT : 1 retry
这是糟糕的设计
private interface BackoffStrategy
extends Func1<Observable<? extends Throwable>, Observable<?>> {
为什么需要在只创建另一个序列的类中实现rx接口?
我使用lambdas重写代码并将代码从BackoffStrategy.call
移到序列
BackoffStrategy backoffStrategy = new BaseBackoffStrategy();
List<CharSequence> observableList = Arrays.asList("a");
Observable.from(observableList)
.flatMap(charSequence -> {
if (charSequence.length() == 1) {
return Observable.error(new RuntimeException("Too short"));
} else {
return Observable.just(charSequence);
}
})
.retryWhen(observable ->
observable
.filter(backoffStrategy::isApplicable)
.doOnNext(next -> System.out.println("Appropriate throwable is thrown!"))
.zipWith(Observable.range(1, 3 + 1), Tuple::new)
.flatMap(tuple -> {
Integer attempts = tuple.getRight();
if (attempts <= 3) {
System.out.println(new Date().toGMTString() + " : " + attempts + " retry");
return Observable.timer((long) Math.pow(2, attempts), TimeUnit.SECONDS);
} else {
return Observable.error(tuple.getLeft());
}
})
)
.toBlocking()
.subscribe(
next -> System.out.println("Next: " + next),
error -> System.out.println("Error: " + error),
() -> System.out.println("Completed")
);
输出
Appropriate throwable is thrown!
7 Oct 2016 12:24:24 GMT : 1 retry
Appropriate throwable is thrown!
7 Oct 2016 12:24:26 GMT : 2 retry
Appropriate throwable is thrown!
7 Oct 2016 12:24:30 GMT : 3 retry
Appropriate throwable is thrown!
Error: java.lang.RuntimeException: Too short
Tuple
班
private static class Tuple<T, V> {
private final T left;
private final V right;
public Tuple(T left, V right) {
this.left = left;
this.right = right;
}
public T getLeft() {
return left;
}
public V getRight() {
return right;
}
}