进入 multi-window 模式时奇怪的生命周期回调排序
Strange lifecycle callbacks ordering when entering multi-window mode
我在使用 RxJava、Retrofit 和 Multi-Window 模式时遇到问题...
我在 Activity 中使用 Retrofit 调用我们自己的 api(实际代码比这稍微复杂一点):
api.getEvent(...)
.subscribeOn(Schedulers.io())
.observeOn(AndroidScheduler.mainThread())
.subscribe(event -> setupUI(event),
throwable -> showSnackbar(throwable));
当应用程序处于 "normal" 模式(全屏)时,一切运行良好...我可以将应用程序放入背景,将其放回前台,api 调用方法是再次调用(它位于 onResume 方法中 - 有点)并且 UI 绘制没有问题。
当我激活 Multi-Window 模式时,调用了 onResume,成功调用了 api 方法,但从未到达 subscribe() 方法。
这种情况的堆栈跟踪是:
Retrofit: java.io.InterruptedIOException: thread interrupted
at okio.Timeout.throwIfReached(Timeout.java:145)
at okio.Okio.write(Okio.java:77)
at okio.RealBufferedSink.flush(RealBufferedSink.java:221)
at com.squareup.okhttp.internal.framed.Http2$Writer.flush(Http2.java:381)
at com.squareup.okhttp.internal.framed.FramedConnection.newStream(FramedConnection.java:283)
at com.squareup.okhttp.internal.framed.FramedConnection.newStream(FramedConnection.java:249)
at com.squareup.okhttp.internal.http.Http2xStream.writeRequestHeaders(Http2xStream.java:135)
at com.squareup.okhttp.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:710)
at com.facebook.stetho.okhttp.StethoInterceptor.intercept(StethoInterceptor.java:67)
at com.squareup.okhttp.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:695)
at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:576)
at com.squareup.okhttp.Call.getResponse(Call.java:287)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:243)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:205) at com.squareup.okhttp.Call.execute(Call.java:80)
at com.newrelic.agent.android.instrumentation.okhttp2.CallExtension.execute(CallExtension.java:43)
at retrofit.client.OkClient.execute(OkClient.java:53)
at com.newrelic.agent.android.instrumentation.retrofit.ClientExtension.execute(ClientExtension.java:42)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
at retrofit.RestAdapter$RestHandler.access0(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:265)
at retrofit.RxSupport.run(RxSupport.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at retrofit.Platform$Android.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:761)
应用程序没有崩溃,但 UI 保持 "placeholder" 状态并且加载 ProgressBar 会一直持续。
编辑: 我在其他活动中有相同的代码结构。不过这个问题没有出现在其他任何地方。
当应用进入 multi-window 模式时,会发生一些奇怪的生命周期回调序列。我已经记录了 onStart
、onResume
、onPause
和 onStop
。查看结果:
pause
stop
start
resume
pause
因此,最初打开的应用程序首先失去焦点,然后获得焦点,然后再次失去焦点(焦点转到下一个 window)。
我认为您在 onPause
取消订阅,因为您在 onResume
开始订阅。这就是为什么 subscribe()
永远不会被调用的原因,因为它会立即被取消订阅。
我在使用 RxJava、Retrofit 和 Multi-Window 模式时遇到问题... 我在 Activity 中使用 Retrofit 调用我们自己的 api(实际代码比这稍微复杂一点):
api.getEvent(...)
.subscribeOn(Schedulers.io())
.observeOn(AndroidScheduler.mainThread())
.subscribe(event -> setupUI(event),
throwable -> showSnackbar(throwable));
当应用程序处于 "normal" 模式(全屏)时,一切运行良好...我可以将应用程序放入背景,将其放回前台,api 调用方法是再次调用(它位于 onResume 方法中 - 有点)并且 UI 绘制没有问题。 当我激活 Multi-Window 模式时,调用了 onResume,成功调用了 api 方法,但从未到达 subscribe() 方法。 这种情况的堆栈跟踪是:
Retrofit: java.io.InterruptedIOException: thread interrupted
at okio.Timeout.throwIfReached(Timeout.java:145)
at okio.Okio.write(Okio.java:77)
at okio.RealBufferedSink.flush(RealBufferedSink.java:221)
at com.squareup.okhttp.internal.framed.Http2$Writer.flush(Http2.java:381)
at com.squareup.okhttp.internal.framed.FramedConnection.newStream(FramedConnection.java:283)
at com.squareup.okhttp.internal.framed.FramedConnection.newStream(FramedConnection.java:249)
at com.squareup.okhttp.internal.http.Http2xStream.writeRequestHeaders(Http2xStream.java:135)
at com.squareup.okhttp.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:710)
at com.facebook.stetho.okhttp.StethoInterceptor.intercept(StethoInterceptor.java:67)
at com.squareup.okhttp.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:695)
at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:576)
at com.squareup.okhttp.Call.getResponse(Call.java:287)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:243)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:205) at com.squareup.okhttp.Call.execute(Call.java:80)
at com.newrelic.agent.android.instrumentation.okhttp2.CallExtension.execute(CallExtension.java:43)
at retrofit.client.OkClient.execute(OkClient.java:53)
at com.newrelic.agent.android.instrumentation.retrofit.ClientExtension.execute(ClientExtension.java:42)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
at retrofit.RestAdapter$RestHandler.access0(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:265)
at retrofit.RxSupport.run(RxSupport.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at retrofit.Platform$Android.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:761)
应用程序没有崩溃,但 UI 保持 "placeholder" 状态并且加载 ProgressBar 会一直持续。
编辑: 我在其他活动中有相同的代码结构。不过这个问题没有出现在其他任何地方。
当应用进入 multi-window 模式时,会发生一些奇怪的生命周期回调序列。我已经记录了 onStart
、onResume
、onPause
和 onStop
。查看结果:
pause
stop
start
resume
pause
因此,最初打开的应用程序首先失去焦点,然后获得焦点,然后再次失去焦点(焦点转到下一个 window)。
我认为您在 onPause
取消订阅,因为您在 onResume
开始订阅。这就是为什么 subscribe()
永远不会被调用的原因,因为它会立即被取消订阅。