【问题标题】:RxJava: Error occurred when trying to propagate error to Observer.onErrorRxJava:尝试将错误传播到 Observer.onError 时发生错误
【发布时间】:2015-10-07 13:54:46
【问题描述】:

我在 Rx 库中收到 IllegalStateException 错误,我不知道问题的根源在哪里,无论是 RxJava 还是我可能做错了什么。

当证书固定(发生在所有服务器请求上)时发生致命崩溃,但似乎指向会话超时或注销并重新登录。重现步骤(大约发生 25% 的时间)如下:登录、打开列表项目 - 一直滚动结束 - 注销 - 重新登录 - 打开应用程序 - 关闭应用程序 -> 崩溃!

有人对如何防止这种情况有任何想法吗?我在这里发现了一个类似的问题Observer.onError firing off inconsistently

java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:62)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4867)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
   at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: rx.exceptions.OnErrorFailedException: Error occurred when trying to propagate error to Observer.onError
   at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:201)
   at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:111)
   at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:159)
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4867)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
   at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: rx.exceptions.CompositeException: 2 exceptions occurred. 
   at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:201)
   at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:111)
   at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:159)
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4867)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
   at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: rx.exceptions.CompositeException$CompositeExceptionCausalChain: Chain of Causes for CompositeException In Order Received =>
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionExceptionSize(SessionDataWriter.java:597)
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionExceptionSize(SessionDataWriter.java:600)
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionExceptionSize(SessionDataWriter.java:600)
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionSize(SessionDataWriter.java:533)
   at com.crashlytics.android.SessionDataWriter.getEventAppSize(SessionDataWriter.java:492)
   at com.crashlytics.android.CrashlyticsUncaughtExceptionHandler.writeSessionEvent(CrashlyticsUncaughtExceptionHandler.java:956)
   at com.crashlytics.android.CrashlyticsUncaughtExceptionHandler.access$200(CrashlyticsUncaughtExceptionHandler.java:56)
   at com.crashlytics.android.CrashlyticsUncaughtExceptionHandler$7.call(CrashlyticsUncaughtExceptionHandler.java:274)
   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
   at java.util.concurrent.FutureTask.run(FutureTask.java:137)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
   at io.fabric.sdk.android.services.common.ExecutorUtils$1$1.onRun(ExecutorUtils.java:58)
   at io.fabric.sdk.android.services.common.BackgroundPriorityRunnable.run(BackgroundPriorityRunnable.java:13)
   at java.lang.Thread.run(Thread.java:856)

【问题讨论】:

  • 嗨,斯科特。请问有可能知道Android版本,RxJava版本,RxAndroid版本吗?您是否妥善处理了所有订阅?
  • io.reactivex:rxandroid:0.24.0 io.reactivex:rxjava:1.0.12 Android version 5.1 是的,我正在取消订阅我的所有订阅,然后将它们设置为 null
  • 你能试试 RxAndroid 1.0.1 https://github.com/ReactiveX/RxAndroid/releases/tag/v1.0.1 吗?
  • 谢谢@IvanMorgillo 我会这样做,看看这是否还在发生。谢谢

标签: android exception rx-java onerror rx-android


【解决方案1】:

发生的情况是,您在 Subscriber 中的 onError 实现抛出了一个违反 Observable 合约的未经检查的异常,这会中止在 observeOn 调度程序中抛出 OnErrorFailedException 的 observable 处理。

【讨论】:

  • 值得指出的是,如果您尝试通过登录 onError 实现来调试它,您可能在 logcat 中看不到它。你最好用断点调试。这就是让我最初看不到问题的原因。
  • 如何在onError() 回调中跟踪确切的错误而不是接收这个通用堆栈跟踪?
  • 如何解决这个问题?
  • 如何解决?您在 onError 的实现中收到 Throwable ,然后在处理该错误时导致另一个错误。我会修复你的实现,所以它不会那样做。为了帮助您调试,您可以通过使用 try catch 包装 onError 实现来记录抛出的错误。
【解决方案2】:

您可能从onError 回调的某处传递了一个活动上下文。当我尝试显示一个 AlertDialog 时发生这种情况 - 将特定的 Activity 上下文传递给它 - 并在该对话框出现之前按下后退按钮。我的建议是不要以这种方式传递 Activity 上下文。

【讨论】:

  • 这听起来很具体
  • @CarloLópezScutaro 是什么导致了您的问题?
  • 这发生在我身上。完全相同的场景。你是如何最终创建对话框的?我将对话框创建抽象为一个 util 类,因此我需要向它传递一个上下文来创建 AlertDialog。
  • 好的,但是如果我们需要在调用onError 时创建一个对话框?
  • @Choletski 如果您显示片段中的对话框,请尝试使用if(activity != null && isAdded()){ } 包装您的代码。它应该防止这种情况下的 IllegalStateException。
【解决方案3】:

如果你想在 onError 中更新 UI,试试吧:

api.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber(){....})

【讨论】:

    【解决方案4】:

    这就是我解决问题的方法:

    public abstract class MyNetworkSubscriber<T> extends Subscriber<T> {
    
    @Override
    public void onCompleted() {}
    
    @Override
    public void onError(Throwable e) {
        if (e instanceof HttpException) {
            ResponseBody responseBody = ((HttpException) e).response().errorBody();
            try {
                if (responseBody != null) {
                    MyError error = new Gson().fromJson(responseBody.string(), MyError.class);
                    onErrorCode(error);
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        } else {
            e.printStackTrace();
        }
    }
    
    public void onErrorCode(MyError error){};
    }
    

    出于某种原因,OkHttp 迫使我捕捉 onError,所以我照做了。如果我不这样做,OkHttp/Retrofit 将崩溃,应用程序将关闭。

    通过提供此解决方案,

    1. 您可以选择覆盖您自己的onErrorCode 并获取更详细的对象作为来自您的 API 的错误,但您不必这样做。
    2. OnError 被覆盖,不再出现疯狂的崩溃。
    3. 最后但同样重要的是,由于&lt;T&gt;,它仍然是通用的!

    您还可以强制覆盖 onComplete 和 onError 以使方法抽象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-07
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-09
      • 1970-01-01
      相关资源
      最近更新 更多