Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何忽略错误并继续无限流?_Android_Rx Java_Rx Android - Fatal编程技术网

Android 如何忽略错误并继续无限流?

Android 如何忽略错误并继续无限流?,android,rx-java,rx-android,Android,Rx Java,Rx Android,我想知道如何忽略异常并继续无限流(以我的位置流为例) 我正在获取当前用户位置(使用),然后将它们发送到我的API(使用) 在我的例子中,当在网络调用期间发生异常(例如超时)时,调用onError方法并停止流本身。如何避免呢 活动: private RestService mRestService; private Subscription mSubscription; private LocationRequest mLocationRequest = LocationRequest.creat

我想知道如何忽略异常并继续无限流(以我的位置流为例)

我正在获取当前用户位置(使用),然后将它们发送到我的API(使用)

在我的例子中,当在网络调用期间发生异常(例如超时)时,调用
onError
方法并停止流本身。如何避免呢

活动:

private RestService mRestService;
private Subscription mSubscription;
private LocationRequest mLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(100);
...
private void start() {
    mRestService = ...;
    ReactiveLocationProvider reactiveLocationProvider = new ReactiveLocationProvider(this);
    mSubscription = reactiveLocationProvider.getUpdatedLocation(mLocationRequest)
            .buffer(50)
            .flatMap(locations -> mRestService.postLocations(locations)) // can throw exception
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe();
}
恢复服务:

public interface RestService {
    @POST("/.../")
    Observable<Response> postLocations(@Body List<Location> locations);
}
公共接口RestService{
@职位(“/…/”)
可观察的位置(@身体列表位置);
}

您可能需要使用其中一个

  • 下一步( )-指示可观察对象在遇到错误时发出一系列项
  • onErrorReturn( )-指示可观察对象在遇到错误时发出特定项
  • OneExceptionResumeNext( )-指示可观察对象在遇到异常(但不是其他类型的可丢弃)后继续发射项目
  • 重试( )-如果源可观测对象发出错误,请重新订阅它,希望它不会出错
  • retryWhen( )-如果源可观察对象发出错误,则将该错误传递给另一个可观察对象,以确定是否重新订阅源

特别是
重试
OneExceptionResumeNext
在您的情况下看起来很有希望。

尝试在Observable.defer调用中调用rest服务。这样,对于每个调用,您都有机会使用自己的“onErrorResumeNext”,错误不会导致您的主流完成

reactiveLocationProvider.getUpdatedLocation(mLocationRequest)
  .buffer(50)
  .flatMap(locations ->
    Observable.defer(() -> mRestService.postLocations(locations))
      .onErrorResumeNext(<SOME_DEFAULT_TO_REACT_TO>)
  )
........
reactiveLocationProvider.getUpdatedLocation(mlLocationRequest)
.缓冲器(50)
.flatMap(位置->
可观察。延迟(()->mRestService.postLocations(位置))
.onErrorResumeNext()
)
........

该解决方案最初来自此线程->,但我认为它也适用于您的情况。

mRestService.postLocations(locations)
发出一个项目,然后完成。 如果发生错误,则会发出错误,从而完成流

当您在
flatMap
中调用此方法时,错误将继续出现在“主”流中,然后流停止

您可以做的是将错误转换为另一项(如下所述:),但不是在主流上(我想您已经尝试过),而是在
mRestService.postLocations(locations)

这样,此调用将发出一个错误,该错误将被转换为一个项目/另一个可观察项,然后完成。(不调用
onError

在消费者视图中,
mRestService.postLocations(locations)
将发出一个项目,然后完成,就像一切都成功一样

mSubscription = reactiveLocationProvider.getUpdatedLocation(mLocationRequest)
        .buffer(50)
        .flatMap(locations -> mRestService.postLocations(locations).onErrorReturn((e) -> Collections.emptyList()) // can't throw exception
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe();

只要粘贴@MikeN答案中的链接信息,以防丢失:

import rx.Observable.Operator;
import rx.functions.Action1;

public final class OperatorSuppressError<T> implements Operator<T, T> {
    final Action1<Throwable> onError;

    public OperatorSuppressError(Action1<Throwable> onError) {
        this.onError = onError;
    }

    @Override
    public Subscriber<? super T> call(final Subscriber<? super T> t1) {
        return new Subscriber<T>(t1) {

            @Override
            public void onNext(T t) {
                t1.onNext(t);
            }

            @Override
            public void onError(Throwable e) {
                onError.call(e);
            }

            @Override
            public void onCompleted() {
                t1.onCompleted();
            }

        };
    }
}
但是,请注意,这会抑制来自 如果在抛出异常后链中有onNext,则为 仍然有可能该来源将被取消订阅


对解决方案(@MikeN)稍作修改,以使有限流能够完成:

import rx.Observable.Operator;
import rx.functions.Action1;

public final class OperatorSuppressError<T> implements Operator<T, T> {
    final Action1<Throwable> onError;

    public OperatorSuppressError(Action1<Throwable> onError) {
        this.onError = onError;
    }

    @Override
    public Subscriber<? super T> call(final Subscriber<? super T> t1) {
        return new Subscriber<T>(t1) {

            @Override
            public void onNext(T t) {
                t1.onNext(t);
            }

            @Override
            public void onError(Throwable e) {
                onError.call(e);
                //this will allow finite streams to complete
                t1.onCompleted();
            }

            @Override
            public void onCompleted() {
                t1.onCompleted();
            }

        };
    }
}
导入rx.Observable.Operator;
导入rx.functions.Action1;
公共最终类运算符SuppressError实现运算符{
最终行动1:一个错误;
公共运营商支持错误(操作1错误){
this.onError=onError;
}
@凌驾

公共订阅服务器添加此问题的我的解决方案:

privider
    .compose(ignoreErrorsTransformer)
    .subscribe()

private final Observable.Transformer<ResultType, ResultType> ignoreErrorsTransformer =
        new Observable.Transformer<ResultType, ResultType>() {
            @Override
            public Observable<ResultType> call(Observable<ResultType> resultTypeObservable) {
                return resultTypeObservable
                        .materialize()
                        .filter(new Func1<Notification<ResultType>, Boolean>() {
                            @Override
                            public Boolean call(Notification<ResultType> resultTypeNotification) {
                                return !resultTypeNotification.isOnError();
                            }
                        })
                        .dematerialize();

            }
        };
privider
.编写(ignoreErrorsTransformer)
.subscribe()
私人最终可观测变压器信号错误变压器=
新的Observable.Transformer(){
@凌驾
公共可观察调用(可观察结果类型可观察){
返回结果类型可观察
.具体化
.filter(新函数1(){
@凌驾
公共布尔调用(通知结果类型通知){
return!resultTypeNotification.IsError();
}
})
.非物质化();
}
};

如果只想忽略平面图中的错误而不返回元素,请执行以下操作:

flatMap(item -> 
    restService.getSomething(item).onErrorResumeNext(Observable.empty())
);

这是我的kotlin扩展函数,用于忽略错误

fun <T> Observable<T>.ignoreErrors(errorHandler: (Throwable) -> Unit) =
    retryWhen { errors ->
        errors
            .doOnNext { errorHandler(it) }
            .map { 0 }
    }
fun Observable.ignoreErrors(errorHandler:(Throwable)->Unit)=
retryWhen{errors->
错误
.doOnNext{errorHandler(it)}
.map{0}
}
这利用
retryWhen
以不确定的方式重新订阅上游,同时仍然允许您以非终端方式处理错误


这感觉很危险

对于Rxjava2,我们可以调用重载的flatmap With delayErrors参数:

将其作为true传递时:

来自当前Flowable和所有内部发布服务器的异常将被延迟,直到所有这些异常都终止。如果为false,则第一个发出异常信号的异常将立即终止整个序列


这个答案可能有点晚,但如果有人偶然发现了这个问题,可以使用Jacke Wharton的现成继电器库,而不是重新发明轮子

有很好的文档,但本质上,中继是一个主题,除非没有调用onComplete或onError的能力

这些选择包括:

行为可靠性

Relay that emits the most recent item it has observed and all subsequent observed items to each subscribed Observer.
//观察者将接收所有事件。
BehaviorRelay relay=BehaviorRelay.createDefault(“默认”);
转播.订阅(观察员);
接力。接受(“一”);
接力。接受(“两”);
接力。接受(“三”);
//观察员将收到“一”、“二”和“三”事件,但不会收到“零”
BehaviorRelay relay=BehaviorRelay.createDefault(“默认”);
继电器。接受(“零”);
接力。接受(“一”);
转播.订阅(观察员);
接力。接受(“两”);
接力。接受(“三”);
发布继电器Relay that emits the most recent item it has observed and all subsequent observed items to each subscribed Observer.
    // observer will receive all events.
    BehaviorRelay<Object> relay = BehaviorRelay.createDefault("default");
    relay.subscribe(observer);
    relay.accept("one");
    relay.accept("two");
    relay.accept("three");

    // observer will receive the "one", "two" and "three" events, but not "zero"
    BehaviorRelay<Object> relay = BehaviorRelay.createDefault("default");
    relay.accept("zero");
    relay.accept("one");
    relay.subscribe(observer);
    relay.accept("two");
    relay.accept("three");

    PublishRelay<Object> relay = PublishRelay.create();
    // observer1 will receive all events
    relay.subscribe(observer1);
    relay.accept("one");
    relay.accept("two");
    // observer2 will only receive "three"
    relay.subscribe(observer2);
    relay.accept("three");
    ReplayRelay<Object> relay = ReplayRelay.create();
    relay.accept("one");
    relay.accept("two");
    relay.accept("three");
    // both of the following will get the events from above
    relay.subscribe(observer1);
    relay.subscribe(observer2);
mSubscription = reactiveLocationProvider.getUpdatedLocation(mLocationRequest)
    .buffer(50)
    .flatMapMaybe(locations -> Maybe.just(mRestService.postLocations(locations).onErrorComplete()) // skip item
    .subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe();