Strange lifecycle callbacks ordering when entering multi-window mode
Asked Answered
A

1

8

I'm having a problem with RxJava, Retrofit and Multi-Window mode... I'm calling our own api with Retrofit inside an Activity (the actual code is a little bit more complex than this):

api.getEvent(...)
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidScheduler.mainThread())
  .subscribe(event -> setupUI(event),
             throwable -> showSnackbar(throwable));

When the app is in "normal" mode (full-screen) everything runs fine...I can put the app in bg, put it back to foreground and the api call method is called again (it lies in the onResume method - kind of) and the UI is drawn without problems. When I activate the Multi-Window mode, instead, onResume is called, the api method is called with success but the subscribe() method is never reached. The stacktrace for this situation is:

Retrofit: java.io.InterruptedIOException: thread interrupted
       at okio.Timeout.throwIfReached(Timeout.java:145)
       at okio.Okio$1.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.access$100(RestAdapter.java:220)
       at retrofit.RestAdapter$RestHandler$1.invoke(RestAdapter.java:265)
       at retrofit.RxSupport$2.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$2$1.run(Platform.java:142)
       at java.lang.Thread.run(Thread.java:761)

The app doesn't crash but the UI stays in a "placeholder" state and the loading ProgressBar goes forever.

EDIT: I have the same code structure in other activities. The issue doesn't appear nowhere else though.

Almund answered 3/4, 2017 at 10:23 Comment(2)
Do you change the focused window when you perform request?Mitchel
Nope...the code is the same...on the phone the only thing I do is to activate the multi-window mode when I'm in the activitySap
M
2

There's a bit strange sequence of lifecycle callbacks happening when an app enters into multi-window mode. I've logged onStart, onResume, onPause and onStop. See results:

enter image description here

pause
stop
start
resume
pause

So, first initially opened app loses focus, then it gains focus and later it loses focus again (focus goes to the next window).

I believe you are unsubscribing in onPause, because you initiated subscription in onResume. And that's why subscribe() never happens to be called, because it is being unsubscribed immediately.

Mitchel answered 7/4, 2017 at 6:1 Comment(1)
nice catch! That was exactly the cause of the issue...I had to move the Subscription unsubscribe method outside the onPause methodSap

© 2022 - 2024 — McMap. All rights reserved.