element-x-android
element-x-android copied to clipboard
Compose 1.7.0 crashes the composer
Contents
This is an issue to describe what's happening when trying to update to the latest Compose BOM. It seems like the new Compose version is having issues with handling focus between Android Views <--> Compose components.
Ideally we should find a solution for this, but if it can't be done maybe we'll need to simplify the UI somehow.
Steps to reproduce
- Use https://github.com/element-hq/element-x-android/pull/3399.
- Go into a room, change into the RTE mode. Notice the focus can take a while to be applied to the edit text.
- Then close the rich text mode.
Outcome
What did you expect?
The plain text/markdown mode should be displayed back.
What happened instead?
The app crashes with:
Thread: main, Exception: java.lang.IllegalArgumentException: performMeasureAndLayout called during measure layout
at androidx.compose.ui.internal.InlineClassHelperKt.throwIllegalArgumentException(InlineClassHelper.kt:34)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout-0kLqBqw(MeasureAndLayoutDelegate.kt:874)
at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout-0kLqBqw(AndroidComposeView.android.kt:1285)
at androidx.compose.ui.node.LayoutNode.forceRemeasure(LayoutNode.kt:1295)
at androidx.compose.foundation.lazy.LazyListBeyondBoundsState.remeasure(LazyListBeyondBoundsModifier.kt:39)
at androidx.compose.foundation.lazy.layout.LazyLayoutBeyondBoundsModifierLocal.layout-o7g1Pn8(LazyLayoutBeyondBoundsModifierLocal.kt:108)
at androidx.compose.ui.focus.BeyondBoundsLayoutKt.searchBeyondBounds--OM-vw8(BeyondBoundsLayout.kt:45)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.generateAndSearchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:160)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.searchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:188)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.generateAndSearchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:155)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.twoDimensionalFocusSearch-sMXa3k8(TwoDimensionalFocusSearch.kt:81)
at androidx.compose.ui.focus.FocusTraversalKt.focusSearch-0X8WOeE(FocusTraversal.kt:109)
at androidx.compose.ui.focus.FocusOwnerImpl.focusSearch-ULY8qGw(FocusOwnerImpl.kt:247)
at androidx.compose.ui.platform.AndroidComposeView.focusSearch(AndroidComposeView.android.kt:855)
at android.view.ViewGroup.focusSearch(ViewGroup.java:1081)
at android.view.ViewGroup.focusSearch(ViewGroup.java:1081)
at android.view.View.focusSearch(View.java:13798)
at android.widget.TextView.hasEditorInFocusSearchDirection(TextView.java:9722)
at android.widget.TextView.onCreateInputConnection(TextView.java:9748)
at androidx.appcompat.widget.AppCompatEditText.onCreateInputConnection(AppCompatEditText.java:270)
at android.view.inputmethod.InputMethodManager.createInputConnection(InputMethodManager.java:4448)
at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:2735)
at android.view.inputmethod.InputMethodManager.startInputOnWindowFocusGainInternal(InputMethodManager.java:976)
at android.view.inputmethod.InputMethodManager.checkFocus(InputMethodManager.java:3005)
at android.view.inputmethod.InputMethodManager.restartInput(InputMethodManager.java:2584)
at android.widget.TextView.setKeyListener(TextView.java:2694)
at androidx.appcompat.widget.AppCompatEditText.initEmojiKeyListener(AppCompatEditText.java:151)
at androidx.appcompat.widget.AppCompatEditText.(AppCompatEditText.java:117)
at androidx.appcompat.widget.AppCompatEditText.(AppCompatEditText.java:96)
at androidx.appcompat.widget.AppCompatEditText.(AppCompatEditText.java:92)
at io.element.android.libraries.textcomposer.components.markdown.MarkdownEditText.(MarkdownEditText.kt:24)
at io.element.android.libraries.textcomposer.components.markdown.MarkdownTextInputKt$MarkdownTextInput$1$1.invoke(MarkdownTextInput.kt:93)
at io.element.android.libraries.textcomposer.components.markdown.MarkdownTextInputKt$MarkdownTextInput$1$1.invoke(MarkdownTextInput.kt:92)
at androidx.compose.ui.viewinterop.ViewFactoryHolder.(AndroidView.android.kt:344)
at androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1$1.invoke(AndroidView.android.kt:275)
at androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1$1.invoke(AndroidView.android.kt:274)
at androidx.compose.runtime.changelist.Operation$InsertNodeFixup.execute(Operation.kt:583)
at androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations(Operations.kt:309)
at androidx.compose.runtime.changelist.FixupList.executeAndFlushAllPendingFixups(FixupList.kt:50)
at androidx.compose.runtime.changelist.Operation$InsertSlotsWithFixups.execute(Operation.kt:550)
at androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations(Operations.kt:309)
at androidx.compose.runtime.changelist.ChangeList.executeAndFlushAllPendingChanges(ChangeList.kt:81)
at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:984)
at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1013)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1150)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:3874)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:3874)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:649)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:635)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto(SubcomposeLayout.kt:516)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:488)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:479)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:463)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(SubcomposeLayout.kt:895)
at io.element.android.features.messages.impl.ExpandableBottomSheetScaffoldKt$ExpandableBottomSheetScaffold$2$1.invoke-0kLqBqw(ExpandableBottomSheetScaffold.kt:124)
at io.element.android.features.messages.impl.ExpandableBottomSheetScaffoldKt$ExpandableBottomSheetScaffold$2$1.invoke(ExpandableBottomSheetScaffold.kt:123)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:725)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:135)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:316)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:315)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2441)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:502)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:258)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1775)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:40)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:696)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.kt:1221)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release$default(LayoutNode.kt:1212)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:369)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:566)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:534)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:390)
at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout(AndroidComposeView.android.kt:1273)
at androidx.compose.ui.node.Owner.measureAndLayout$default(Owner.kt:248)
at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1555)
at android.view.View.draw(View.java:23923)
at android.view.View.updateDisplayListIfDirty(View.java:22787)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4543)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4516)
at android.view.View.updateDisplayListIfDirty(View.java:22743)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4543)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4516)
at android.view.View.updateDisplayListIfDirty(View.java:22743)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4543)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4516)
at android.view.View.updateDisplayListIfDirty(View.java:22743)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4543)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4516)
at android.view.View.updateDisplayListIfDirty(View.java:22743)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4543)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4516)
at android.view.View.updateDisplayListIfDirty(View.java:22743)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4543)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4516)
at android.view.View.updateDisplayListIfDirty(View.java:22743)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:706)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:712)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:810)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:5144)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4835)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4011)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2650)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9529)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1343)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1352)
at android.view.Choreographer.doCallbacks(Choreographer.java:952)
at android.view.Choreographer.doFrame(Choreographer.java:882)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1326)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8282)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:554)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:885)
Your phone model
Xiaomi Mi 9T
Operating system version
Android 14
Application version and app store
No response
Homeserver
No response
Will you send logs?
Yes
Are you willing to provide a PR?
Yes
Apparently this can be worked around by overriding this in MarkdownEditText:
override fun focusSearch(direction: Int): View? {
return null
}
Although I'm not sure about the implications. It should be fine since we don't care about the next focused view at all in this component.
Will you apply this patch on #3399?
Yes, it's already in use there.
Hello @jmartinesp I believe that we can we close this issue?
I think the workaround is not even needed with Compose 1.8.0.