eneim
05/05/2025, 12:53 PMWrappedComposition
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:
// 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 ...
shikasd
05/05/2025, 2:51 PMeneim
05/06/2025, 6:09 AM