flexbox-layout
flexbox-layout copied to clipboard
ComposeView in flexbox crashes, because it is not attached when measured
- [x] I have searched existing issues and confirmed this is not a duplicate
Issues and steps to reproduce
When I try to use ComposeView
or AbstractComposeView
with FlexboxLayoutManager
, it crashes due to
java.lang.IllegalStateException: Cannot locate windowRecomposer; View androidx.compose.ui.platform.ComposeView{7ae95e1 V.E...... ......I. 0,0-0,0} is not attached to a window
at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer.android.kt:294)
at androidx.compose.ui.platform.AbstractComposeView.resolveParentCompositionContext(ComposeView.android.kt:242)
at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(ComposeView.android.kt:249)
...
at android.view.View.measure(View.java:25466)
at com.google.android.flexbox.FlexboxHelper.calculateFlexLines(FlexboxHelper.java:477)
at com.google.android.flexbox.FlexboxHelper.calculateHorizontalFlexLines(FlexboxHelper.java:249)
at com.google.android.flexbox.FlexboxLayoutManager.updateLayoutState(FlexboxLayoutManager.java:2112)
at com.google.android.flexbox.FlexboxLayoutManager.handleScrollingMainOrientation(FlexboxLayoutManager.java:1993)
at com.google.android.flexbox.FlexboxLayoutManager.scrollVerticallyBy(FlexboxLayoutManager.java:1957)
at androidx.recyclerview.widget.RecyclerView.scrollStep(RecyclerView.java:2009)
This basically prevents usage of FlexboxLayoutManager
with compose views.
Root cause is that FlexboxLayoutManager
attempts to measure composable before it is attached to window, which crashes in ComposeView:
/**
* Get or lazily create a [Recomposer] for this view's window. The view must be attached
* to a window with a [ViewTreeLifecycleOwner] registered at the root to access this property.
*/
@OptIn(InternalComposeUiApi::class)
internal val View.windowRecomposer: Recomposer
get() {
check(isAttachedToWindow) {
"Cannot locate windowRecomposer; View $this is not attached to a window"
}
val rootView = contentChild
return when (val rootParentRef = rootView.compositionContext) {
null -> WindowRecomposerPolicy.createAndInstallWindowRecomposer(rootView)
is Recomposer -> rootParentRef
else -> error("root viewTreeParentCompositionContext is not a Recomposer")
}
}
Expected behavior
It should not crash, as it does not crash with other managers (e.g. LinearLayourManager
)
Version of the flexbox library
Flexbox: 3.0.0 Compose: 1.3.0 Recycler view: 1.3.0-rc1
Link to code
class ComposeAdapter : RecyclerView.Adapter<ComposeHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): MyComposeViewHolder {
return ComposeHolder(ComposeView(parent.context))
}
class MyComposeViewHolder(
val composeView: ComposeView
) : RecyclerView.ViewHolder(composeView) {
fun bind(input: String) {
composeView.setContent {
MdcTheme {
Text(input)
}
}
}
}