简体   繁体   English

RxJava2 Single已处置后,抛出RuntimeException且未将其捕获

[英]RuntimeException thrown and not caught in RxJava2 Single after it has been disposed

A RuntimeException thrown inside an RxJava2 Single is not getting caught and is not getting sent to the Observer's onError() method if the observer has been disposed. 如果已丢弃观察者,则不会捕获RxJava2 Single中抛出的RuntimeException,也不会将其发送到Observer的onError()方法。
I understand that calling CompositeDisposable.dispose() means that my Subscriber's onSuccess or onError methods won't be called, but shouldn't the exception be ignored too? 我知道调用CompositeDisposable.dispose()意味着不会调用我的订阅服务器的onSuccess或onError方法,但是也不应忽略该异常吗? Instead the application is crashing because the RuntimeException isn't caught. 相反,由于未捕获RuntimeException,应用程序崩溃了。

Here is the Single, the line with the comment can throw a RuntimeException, if the exception is thrown before a call to the .dispose() method, it get's caught and the error is sent to the subscriber, but if the exception is thrown AFTER a call to .dispose() the app crashes. 这是Single,带有注释的行会引发RuntimeException,如果在调用.dispose()方法之前引发了异常,则会捕获该异常并将错误发送给订阅者,但如果在AFTER之后引发异常对.dispose()的调用导致应用崩溃。

public Single<Submission> getSubmission(final String threadId, final CommentSort sort) {
        return Single.create(new SingleOnSubscribe<Submission>() {
            @Override
            public void subscribe(SingleEmitter<Submission> e) throws Exception {
                // some irrelevant code

                try {
                    submission = reddit.getSubmission(sr); // Can throw RuntimeException
                    e.onSuccess(submission);
                } catch (Exception ex) {
                    e.onError(ex);
                }
            }
        });
    }  

Code where I subscribe to it: 我订阅的代码:

disposables.add(someCompletable
                .andThen(service.getSubmission(threadId, CommentSort.HOT))
                .subscribeOn(schedulerProvider.io())
                .observeOn(schedulerProvider.ui())
                .subscribeWith(new DisposableSingleObserver<Submission>() {
                    @Override
                    public void onSuccess(Submission submission) {
                        // Handle result
                    }

                    @Override
                    public void onError(Throwable e) {
                        // Handle error
                    }
                })
        );

Stacktrace: 堆栈跟踪:

E/AndroidRuntime: FATAL EXCEPTION: RxCachedThreadScheduler-2
Process: com.gmail.jorgegilcavazos.ballislife.debug, PID: 15242
java.lang.RuntimeException: Unable to parse JSON: [{"kind": "Listing", "data": {"modhash": null, "children": [{"kind": "t3", "data
at net.dean.jraw.util.JrawUtils.fromString(JrawUtils.java:182)
at net.dean.jraw.http.RestResponse.<init>(RestResponse.java:64) 
at net.dean.jraw.http.OkHttpAdapter.execute(OkHttpAdapter.java:81)
at net.dean.jraw.http.RestClient.execute(RestClient.java:120)
at net.dean.jraw.RedditClient.execute(RedditClient.java:143)
at net.dean.jraw.RedditClient.execute(RedditClient.java:137)
at net.dean.jraw.RedditClient.getSubmission(RedditClient.java:287)
at com.gmail.jorgegilcavazos.ballislife.network.API.RedditService$10.subscribe(RedditService.java:311)
at io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39)
at io.reactivex.Single.subscribe(Single.java:2656)
at io.reactivex.internal.operators.single.SingleDelayWithCompletable$OtherObserver.onComplete(SingleDelayWithCompletable.java:70)
at io.reactivex.internal.disposables.EmptyDisposable.complete(EmptyDisposable.java:67)
at io.reactivex.internal.operators.completable.CompletableEmpty.subscribeActual(CompletableEmpty.java:27)
at io.reactivex.Completable.subscribe(Completable.java:1592)
at io.reactivex.internal.operators.single.SingleDelayWithCompletable.subscribeActual(SingleDelayWithCompletable.java:36)
at io.reactivex.Single.subscribe(Single.java:2656)

Found the answer: 找到了答案:

RxJava 2 is designed so that no errors can be lost. RxJava 2被设计为不会丢失任何错误。 So when the sequence ends or gets cancelled the emitter has nowhere to send the error, so it gets routed to the RxJavaPlugins.onError . 因此,当序列结束或被取消时,发射器无处发送错误,因此将其路由到RxJavaPlugins.onError
Unlike 1.x, 2.x by default calls Thread.currentThread().getUncaughtExceptionHandler().uncaughtException() which crashes an Android app. 与1.x不同,默认情况下,2.x调用Thread.currentThread().getUncaughtExceptionHandler().uncaughtException()导致Android应用崩溃。

Source 资源
Similar stackoverflow question 类似的stackoverflow问题

In my case, since the subscriber has been disposed I no longer care about the errors that the emitter could throw, so the emitter should check that it has not been disposed of before calling onError() 在我的情况下,由于已经处置了订户,所以我不再关心发射器可能抛出的错误,因此,发射器应在调用onError()之前检查是否已将其onError()

try {
      Submission submission = redditClient.getSubmission(sr);
      e.onSuccess(submission);
} catch (Exception ex) {
      if (!e.isDisposed()) {
           e.onError(ex);
      }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM