Recently, we have a lot of Fatal Exception: Java.lang.illeglegalstateexception.
v15.15.0 and v16.3.0
I attach the entire stack trace errors:
Fatal Exception: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:5401)
at android.view.ViewGroup.addView(ViewGroup.java:5216)
at android.view.ViewGroup.addView(ViewGroup.java:5156)
at android.view.ViewGroup.addView(ViewGroup.java:5128)
at androidx.compose.ui.viewinterop.AndroidViewHolder.<init>(AndroidViewHolder.android.kt:99)
at androidx.compose.ui.viewinterop.ViewFactoryHolder.<init>(AndroidView.android.kt:332)
at androidx.compose.ui.viewinterop.ViewFactoryHolder.<init>(AndroidView.android.kt:323)
at androidx.compose.ui.viewinterop.ViewFactoryHolder.<init>(AndroidView.android.kt:342)
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:585)
at androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations(Operations.kt:310)
at androidx.compose.runtime.changelist.FixupList.executeAndFlushAllPendingFixups(FixupList.java:50)
at androidx.compose.runtime.changelist.Operation$InsertSlotsWithFixups.execute(Operation.kt:552)
at androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations(Operations.kt:310)
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$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:685)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:585)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.java:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.java:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1240)
at android.view.Choreographer.doCallbacks(Choreographer.java:996)
at android.view.ChoreographerExtImpl.checkScrollOptSceneEnable(ChoreographerExtImpl.java:380)
at android.view.Choreographer.doFrame(Choreographer.java:865)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1227)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:233)
at android.os.Looper.loop(Looper.java:344)
at android.app.ActivityThread.main(ActivityThread.java:8249)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)
From this, it becomes clear that the Intercom library uses interoperability between View and Compose, and during the recomposition of a Composable function, an exception is thrown because the View used inside the Composable function already has a parent ViewGroup. This indicates that the same instance of a View is being passed to the Composable function, which is not allowed!
Here’s an example that causes such an error:
val myTextView = TextView(context).apply { text = "Hello" }
@Composable fun MyComposable(someState: Boolean) { Column { // On each recomposition, the same myTextView will be returned AndroidView(factory = { myTextView }) } }
Here’s the correct way to do it:@Composable fun MyComposable(name: String) { AndroidView( factory = { context -> TextView(context) }, update = { view -> view.text = name } ) }
Google guide:
https://developer.android.com/develop/ui/compose/migrate/interoperability-apis/views-in-compose
In the Intercom library, there is a class LegacyMessengerAppCard.kt
where apparently a CardWebView
instance is created first and then passed into a Composable function via AndroidView
, which, as it seems, causes the error.
Please pay attention to this.