RxJava 2.继续重试,同时继续执行其他不同的项目

时间:2017-09-11 08:07:43

标签: android rx-java distinct rx-java2 retrywhen

我有一个可以从很多来源获取物品的观察物:

Source { List<Item> data }

源和项目之间的关系是多对多的,在不同的来源中,项目可能会自行复制。 Item是应该上传到服务器的实体,服务器不接受重复项。为了实现这一点,我合并了Sources并通过它们的ID区分它们的Items,然后将唯一的项目上传到服务器。如下所示:

Observable.merge(source1(), source2(), source3())
            .flatMapIterable(sources -> sources)
            .flatMapIterable(source::getItems)
            .distinct(item -> item.getId())
            .flatMapCompletabale(item -> uploadItem(item))

项目上传可能会发出多个错误,其中一些错误我应该稍后再次尝试上传项目,然后在“失败”的情况下继续执行其他项目。一个正在等待它的重试。

如何推迟重试上传&#39;失败&#39;项目并继续其他项目,而这个项目正在尝试尝试?

提前致谢!

3 个答案:

答案 0 :(得分:2)

要处理一次上传失败,您可以在最后一步添加运算符:

  .flatMapCompletable(item->uploadItem(item))

应该成为

  .flatMapCompletable(item->uploadItem(item)
                              .retryWhen(throwable -> 
                                  throwable.delay(5, TimeUnit.SECONDS)))

编辑:我从this Dan Lew blog entry了解了很多retryWhen()运算符。您会找到几个示例,包括使用zip()运算符和Observable.range(3)来限制重试次数。

答案 1 :(得分:0)

我将此函数放入retryWhen方法并使其正常工作。

public class RetryWithDelay implements Function<Observable<? extends Throwable>, Observable<?>> {

private final int maxRetryCount;
private final int retryDelay;
private int retryCount;
private TimeUnit timeUnit;

public RetryWithDelay(final int maxRetryCount, final int retryDelay, final TimeUnit timeUnit) {
    this.maxRetryCount = maxRetryCount;
    this.retryDelay = retryDelay;
    this.timeUnit = timeUnit;
    this.retryCount = 0;
}

@Override
public Observable<?> apply(final Observable<? extends Throwable> attempts) {
    return attempts.flatMap((Function<Throwable, Observable<?>>) throwable -> {

        if (++retryCount < maxRetryCount) {
            return Observable.timer(retryDelay, timeUnit);
        }

        return Observable.error(throwable);
    });
}
}

答案 2 :(得分:0)

我必须修改以上示例以创建一个Flowable以便在RxJava2项目中的Single时重试:

import io.reactivex.Flowable; import io.reactivex.functions.Function;

import java.util.concurrent.TimeUnit;

public class RetryWithDelay implements Function<Flowable<? extends Throwable>, Flowable<?>> {

    private final int maxRetryCount;
    private final int retryDelay;
    private int retryCount;
    private TimeUnit timeUnit;

    public RetryWithDelay(final int maxRetryCount, final int retryDelay, final TimeUnit timeUnit) {
        this.maxRetryCount = maxRetryCount;
        this.retryDelay = retryDelay;
        this.timeUnit = timeUnit;
        this.retryCount = 0;
    }

    @Override
    public Flowable<?> apply(final Flowable<? extends Throwable> attempts) {

        return attempts.flatMap((Function<Throwable, Flowable<?>>) throwable -> {

            if (++retryCount < maxRetryCount) {
                return Flowable.timer(retryDelay, timeUnit);
            }

            return Flowable.error(throwable);
        });
    } }

并将其应用到我的单曲中:

.retryWhen(new RetryWithDelay(5, 2, TimeUnit.SECONDS))