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