Android 改装/OkHTTP/RxJava间歇性中断异常

Android 改装/OkHTTP/RxJava间歇性中断异常,android,retrofit,rx-java,okhttp,rx-android,Android,Retrofit,Rx Java,Okhttp,Rx Android,我正在使用以下(过时的)库: Retrofit: 1.9.0 OkHTTP: 2.3.0 RxAndroid: 0.24.0 我注意到,每隔一段时间,我就会收到以下POST请求的堆栈跟踪: D/Retrofit: ---> HTTP POST https:xxxxx D/Retrofit: Content-Type: application/x-www-form-urlencoded; charset=UTF-8 D/Retrofit: Content-Length: 396 D

我正在使用以下(过时的)库:

Retrofit: 1.9.0
OkHTTP: 2.3.0
RxAndroid: 0.24.0
我注意到,每隔一段时间,我就会收到以下POST请求的堆栈跟踪:

 D/Retrofit: ---> HTTP POST https:xxxxx
 D/Retrofit: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
 D/Retrofit: Content-Length: 396
 D/Retrofit: ---> END HTTP (396-byte body)
 D/Retrofit: ---- ERROR https:xxxxx
 I/Choreographer: Skipped 33 frames!  The application may be doing too much work on its main thread.
 D/Retrofit: java.io.InterruptedIOException
   at okio.Timeout.throwIfReached(Timeout.java:146)
   at okio.Okio$1.write(Okio.java:75)
   at okio.AsyncTimeout$1.write(AsyncTimeout.java:155)
   at okio.RealBufferedSink.flush(RealBufferedSink.java:201)
   at com.squareup.okhttp.internal.http.HttpConnection.flush(HttpConnection.java:140)
   at com.squareup.okhttp.Connection.makeTunnel(Connection.java:399)
   at com.squareup.okhttp.Connection.upgradeToTls(Connection.java:229)
   at com.squareup.okhttp.Connection.connect(Connection.java:159)
   at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:175)
   at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:120)
   at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:330)
   at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:319)
   at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)
   at com.squareup.okhttp.Call.getResponse(Call.java:271)
   at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:228)
   at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:199)
   at com.squareup.okhttp.Call.execute(Call.java:79)
   at retrofit.client.OkClient.execute(OkClient.java:53)
   at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
   at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
   at java.lang.reflect.Proxy.invoke(Proxy.java:913)
   at $Proxy1.replyTransaction(Unknown Source)
   < App Specific Trace > 
   at rx.Observable$1.call(Observable.java:145)
   at rx.Observable$1.call(Observable.java:137)
   at rx.Observable.unsafeSubscribe(Observable.java:7304)
   at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:47)
   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
   at java.util.concurrent.FutureTask.run(FutureTask.java:266)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
   at java.lang.Thread.run(Thread.java:764)
 D/Retrofit: ---- END ERROR
 retrofit.RetrofitError
     at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:395)
     at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
     at java.lang.reflect.Proxy.invoke(Proxy.java:913)
     at $Proxy1.replyTransaction(Unknown Source)
     < App Specific Trace > 
     at rx.Observable$1.call(Observable.java:145)
     at rx.Observable$1.call(Observable.java:137)
     at rx.Observable.unsafeSubscribe(Observable.java:7304)
     at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:47)
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
     at java.lang.Thread.run(Thread.java:764)
  Caused by: java.io.InterruptedIOException
     at okio.Timeout.throwIfReached(Timeout.java:146)
     at okio.Okio$1.write(Okio.java:75)
     at okio.AsyncTimeout$1.write(AsyncTimeout.java:155)
     at okio.RealBufferedSink.flush(RealBufferedSink.java:201)
     at com.squareup.okhttp.internal.http.HttpConnection.flush(HttpConnection.java:140)
     at com.squareup.okhttp.Connection.makeTunnel(Connection.java:399)
     at com.squareup.okhttp.Connection.upgradeToTls(Connection.java:229)
     at com.squareup.okhttp.Connection.connect(Connection.java:159)
     at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:175)
     at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:120)
     at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:330)
     at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:319)
     at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)
     at com.squareup.okhttp.Call.getResponse(Call.java:271)
     at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:228)
     at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:199)
     at com.squareup.okhttp.Call.execute(Call.java:79)
     at retrofit.client.OkClient.execute(OkClient.java:53)
     at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
     at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240) 
     at java.lang.reflect.Proxy.invoke(Proxy.java:913) 
     at $Proxy1.replyTransaction(Unknown Source) 
     < App Specific Trace > 
     at rx.Observable$1.call(Observable.java:145) 
     at rx.Observable$1.call(Observable.java:137) 
     at rx.Observable.unsafeSubscribe(Observable.java:7304) 
     at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62) 
     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:47) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
     at java.lang.Thread.run(Thread.java:764)
我对这一点的理解是,我收到了一个
中断异常
,因为我在
onPause()
中从
订阅中取消订阅()。我们这样做是为了其他的请求,所以我不知道为什么我只在这里看到它,为什么它会发生

为了提供更多关于这方面的信息,网络调用发生在通过通知操作从锁定屏幕启动的活动中,以强制用户解锁其设备以采取行动

我的问题是为什么会发生这种情况,有没有好的方法来补救?根据一些文章,
onPause()
是您应该取消订阅
observatives
的地方

更多信息请参见


谢谢

这是一个猜测,但可能是在发出中断异常之前,您没有检查订户是否仍在

试试这个:

return Observable.create(new Observable.OnSubscribe<Object>() {
      @Override public void call(Subscriber<? super Object> subscriber) {
        try {
          subscriber.onNext(/* Sync network call here. */);
          subscriber.onCompleted();
        } catch (Exception e) {
          if (!subscriber.isUnsubscribed()) { // <-- check before emitting error
            subscriber.onError(e);
          }
        }
      }
    })
returnobservable.create(newobservable.OnSubscribe()){

@覆盖公共无效调用(订阅方取消订阅后,链不需要再做任何工作,因为我们不再关心输出。我们可以让当前操作完成,并在到达下一个运营商时完全停止工作,但为什么要浪费我们不需要的任何资源?如果有正在进行的网络请求,我们希望取消它。我们可以通过interru来完成此操作正在选择线程。如果/当此线程上的代码检查它是否被中断时,则无需再做任何工作,并且可以抛出
InterruptedIOException

根据调用unsubscribe的确切时间,您可能会或可能不会看到错误。如果在请求开始加载之前或加载完成之后调用unsubscribe,则您可能不会看到此错误

因此,出现这种异常的原因是OkHttp希望在知道您对其结果不感兴趣时立即放弃,而RxJava也不想吞下它,以防它对您很重要

您可以添加一个默认的错误处理程序来抑制不可交付的代码<代码>中断/代码>和<代码> StudioDeOExtExe> /Case>S,这是很少有用的。参见,我相信RxJava 1具有类似的构造,但是您应该考虑迁移到RxJava 2。它实际上不太偏离,并且已经被更新为RXJava 2。
onPause()
不一定是您应该取消订阅的地方。您应该在应用程序逻辑需要的地方以及可以防止内存泄漏的地方取消订阅。

尝试以下方法:

return Observable.create(e -> {
           try {
               e.onNext(...);
           } catch (Exception ex) {
               e.tryOnError(ex);
           }
           e.onComplete();
       });
tryOnError()检查发送错误时是否释放了观察者


参考资料:

注意您正在破坏。如果您调用了
onError
,则不能调用
onCompleted
  @Override
  protected void onPause() {
    super.onPause();
    if (subscription != null) {
      subscription.unsubscribe();
      subscription = null;
      if (condition) {
        finish();
      }
    }
  }
return Observable.create(new Observable.OnSubscribe<Object>() {
      @Override public void call(Subscriber<? super Object> subscriber) {
        try {
          subscriber.onNext(/* Sync network call here. */);
          subscriber.onCompleted();
        } catch (Exception e) {
          if (!subscriber.isUnsubscribed()) { // <-- check before emitting error
            subscriber.onError(e);
          }
        }
      }
    })
return Observable.create(e -> {
           try {
               e.onNext(...);
           } catch (Exception ex) {
               e.tryOnError(ex);
           }
           e.onComplete();
       });