Using Views in Compose issue | Community
Skip to main content

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.

Hey ​@Sergey, Emily here from Support Engineering in Intercom 👋🏼

 

The crash you’re seeing - java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. - is caused by reusing a View instance inside a Composable function with AndroidView. This happens when a View (like a WebView or TextView) is created once and then passed into a Composable, which leads to the same View being added to multiple parents during recomposition, triggering the exception.

To avoid this, do not reuse the same View instance. Instead, always create a new View inside the factory parameter of AndroidView. For Intercom, do not embed the support view directly via AndroidView. Instead, invoke Intercom’s UI through their API (e.g., Intercom.client().present(IntercomSpace.Messages)) rather than embedding the view.

If you’re seeing this in a custom integration, ensure you’re not reusing View instances in Compose, and follow the Compose interoperability guidelines from Google.

 

If you continue to have issues here, could you open up a ticket with our support team for further analysis? 

 

Thanks! 🤩


Hi ​@Emilygav 

Our application does not reuse the same instance of an Android View in a Composable function. I just want to point out that the library intercom-android allows this mistake. Please take a look at the LegacyMessengerAppCard.kt file in this library. In that file, the same instance of CardWebView is passed to the AndroidView() Composable function.

The library uses the AndroidView() Composable function in many places, which indicates interaction between Composable functions and traditional Views. If, in any of these places, the View instance is not created inside the AndroidView() Composable, then each time the Composable function recomposes, a java.lang.IllegalStateException will be thrown.

I believe this is exactly the reason for the issue described in this post:
https://community.intercom.com/mobile-sdks-24/illegalstateexception-the-specified-child-already-has-a-parent-you-must-call-removeview-on-the-child-s-parent-first-4005

Thank you!


Hi ​@Sergey,

Please reach out to our Support Team via the Messenger if you’re still running into this issue that so we can take a look at your set up directly. Thanks!