Currently, the Paging with Network demo uses ReceiveChannel.consumeAsFlow which crashes the App on configuration changes. The reason, IMO, is when the Activity is recreated, the ViewModel's posts value starts collecting again for the new Adapter. This goes against the contract of consumeAsFlow which allows up to one consumer.
How to reproduce:
Open the PagingWithNetwork sample, choose any of the demos, I picked the "NETWORK ONLY (BY ITEM)".
After the first loading finishes, rotate the device -> It crashes. Stack trace is as below:
Process: com.android.example.paging.pagingwithnetwork, PID: 21282
java.lang.IllegalStateException: ReceiveChannel.consumeAsFlow can be collected just once
at kotlinx.coroutines.flow.ChannelAsFlow.markConsumed(Channels.kt:125)
at kotlinx.coroutines.flow.ChannelAsFlow.collect(Channels.kt:150)
at com.android.example.paging.pagingwithnetwork.reddit.ui.SubRedditViewModel$$special$$inlined$map$1.collect(SafeCollector.common.kt:114)
at kotlinx.coroutines.flow.internal.ChannelFlowMerge$collectTo$$inlined$collect$1$lambda$1.invokeSuspend(Merge.kt:67)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at androidx.lifecycle.DispatchQueue.drainQueue(DispatchQueue.kt:76)
at androidx.lifecycle.DispatchQueue.resume(DispatchQueue.kt:55)
at androidx.lifecycle.LifecycleController$observer$1.onStateChanged(LifecycleController.kt:40)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68)
at androidx.lifecycle.ReportFragment$LifecycleCallbacks.onActivityPostCreated(ReportFragment.java:170)
at android.app.Activity.dispatchActivityPostCreated(Activity.java:1216)
at android.app.Activity.performCreate(Activity.java:7821)
at android.app.Activity.performCreate(Activity.java:7801)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3462)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5429)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5337)
at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2063)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7615)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
The fix
This PR use the ReceiveChannel.receiveAsFlow instead. It allows multiple receivers.
The issue
Currently, the Paging with Network demo uses
ReceiveChannel.consumeAsFlow
which crashes the App on configuration changes. The reason, IMO, is when the Activity is recreated, the ViewModel's posts value starts collecting again for the new Adapter. This goes against the contract ofconsumeAsFlow
which allows up to one consumer.How to reproduce:
The fix
This PR use the
ReceiveChannel.receiveAsFlow
instead. It allows multiple receivers.