web-dev-qa-db-ja.com

RxJava:エラーをObserver.onErrorに伝搬しようとしたときにエラーが発生しました

RxライブラリでIllegalStateExceptionエラーが発生し、問題の根本がどこにあるのか、それがRxJavaにあるのか、私が間違っている可能性があるのか​​を正確に知りません。

致命的なクラッシュは、証明書のピン留め(すべてのサーバー要求で発生)が発生しますが、セッションタイムアウトまたはログアウトを指し示しているように見えます。再現手順(時間の約25%が発生)は次のとおりです。最後まで-ログアウト-ログイン-アプリを開く-アプリを閉じる->クラッシュ!

これを防ぐ方法についてのアイデアはありますか?ここで同様の問題を見つけました Observer.onErrorが一貫性なく起動します

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)
37
Scott B

onErrorSubscriber実装がObservableコントラクトに反する未チェックの例外をスローしており、これによりOnErrorFailedExceptionスケジューラーでobserveOnをスローするオブザーバブル処理が中止されています。

46
Dave Moten

おそらく、onErrorコールバックのどこかにActivityコンテキストを渡しているでしょう。これは、特定のアクティビティコンテキストを渡してAlertDialogを表示し、ダイアログが表示される前に戻るボタンを押したときに発生しました。私のアドバイスは、このようにActivityコンテキストを渡さないことです。

11
IgorGanapolsky

これは私が問題を解決した方法です:

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. そして最後になりましたが、<T>

メソッドを抽象化するために、onCompleteとonErrorを強制的にオーバーライドすることもできます。

1
Karl-John Chow