Another observation at <https://cs.android.com/and...
# compose
e
Another observation at https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]ose/ui/platform/Wrapper.android.kt;l=118?q=Wrapper.android.kt So I understand that a
WrappedComposition
will be reused under some conditions to optimize the performance (e.g., using in a PoolingContainer like RecyclerView). However, in such case, it seems that
WrapperComposition.addedToLifecycle
field is never updated after the first set to non-null call. I guess the class assumes that the containing AndroidComposeView is added to at most one lifecycle? But in the case of RecyclerView, we can specify a RecycledViewPool at the Activity's scope, whiles RecyclerView instances using that Pool are in Fragments of that Activity --> an AndroidComposeView could be (re)used across different Lifecycle (i.e. different Fragments). Combine with the code in the 2nd screenshot (onStateChanged), I can see that: if a AndroidComposeView is used to a Fragment A, then re-used-without-decomposing in a Fragment B, if the destruction of Fragment A happens after the creation of Fragment B, then the WrappedComposition will be disposed and the UI is gone. JFYI, the Epoxy library utilizes this Activity-bound Pool by default & I could reproduce the UI-be-gone issue above (not as high confidence, but still). I assume any implementation using a similar Pool has this issue, not Epoxy-specific issue. I think a code change like below can address it:
Copy code
// WrappedComposition.setContent, line 118.
                val lifecycle = it.lifecycleOwner.lifecycle
                lastContent = content
                if (addedToLifecycle != lifecycle) {
                    addedToLifecycle?.removeObserver(this@WrappedComposition) // Added to a new Lifecycle, so it must detach from the old one, if any.
                    addedToLifecycle = lifecycle
                    // this will call ON_CREATE synchronously if we already created
                    lifecycle.addObserver(this)
                } // else ...
s
Please file a bug to Compose bug tracker I think current implementation assumes the composition is not moved between view parents
🫡 1