Home > OS >  Crash when using fragment in AndroidView using compose
Crash when using fragment in AndroidView using compose

Time:12-10

I'm playing around with compose and tried to include a fragment inside a compose AndroidView.

So in my situation, we have AFragment with a ComposeView and inside the ComposeView there is an AndroidView which create a FragmentContainerView and add a PIFragment.

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {
        return ComposeView(requireContext()).apply {
            setContent {
                AppTheme {
                    GalleryScreen(
                        factory = viewModelFactory,
                        remoteConfig = remoteConfig,
                        id = id,
                        currentPosition = currentPositionState,
                        onBack = { router.back(requireActivity()) },
                    ) {
                        AndroidView(
                            modifier = Modifier
                                .fillMaxWidth()
                                .wrapContentHeight(),
                            factory = {
                                FragmentContainerView(context).apply {
                                    id = R.id.pFIC
                                }
                            },
                            update = {
                                childFragmentManager.beginTransaction().replace(
                                    R.id.pFIC,
                                    PIFragment::class.java,
                                    buildArguments(
                                        id = id,
                                        origin = origin,
                                    ), null
                                ).commitAllowingStateLoss()
                            },
                        )
                    }
                }
            }
        }
    }

All was working fine, but when we publish this code in production, we saw crash in firebase:

    java.lang.IllegalArgumentException: No view found for id 0x7f0b072b (...:id/pFIC) for fragment PIFragment{ef1f89b} (bdbe15f0-679d-41bb-8a27-367655f73545 id=0x7f0b072b)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:513)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2180)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
        at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

CodePudding user response:

In fact, the crash was happening after the parent fragment was recreated.

In my case because of navigation:

  • AFragment (with PIFragment)
  • navigate to BFragment
  • back to AFragment

Crash, because the fragment manager is trying to recreate AFragment and PIFragment, but the compose pass is not done so pFIC does not exist yet.

The solution was to remove the PIFragment when the parent fragment view is destroyed.

    override fun onDestroyView() {
        childFragmentManager.findFragmentById(R.id.pFIC)?.let { fragment ->
            childFragmentManager.beginTransaction().remove(fragment).commitAllowingStateLoss()
        }
        super.onDestroyView()
    }
  • Related