I'm trying to inflate a view that contains FragmentContainerView
inside a fragment that's being put into a layout.
Like this:
val transaction = fragmentManager.beginTransaction()
transaction.replace(R.id.main_content, Frag(), "tag");
transaction.commitNowAllowingStateLoss()
where Frag
creates a view that inflates a xml like this one:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:parentTag="android.widget.FrameLayout">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</merge>
But when I execute the code, my app crashes:
Caused by: java.lang.IllegalStateException: FragmentManager is already executing transactions
How can I avoid this error while using FragmentContainerView
(obs.: if I use <fragment>
instead of <androidx.fragment.app.FragmentContainerView>
, everything works fine)
You should always, always use childFragmentManager
when nesting fragments - the childFragmentManager
is never executing transactions when its parent is going through lifecycle changes (which I assume is when you're calling your transaction).
This is actually silently causing issues for you when you use the <fragment>
tag as those lifecycle events don't actually occur as a transaction, but directly as part of inflation. Using the wrong FragmentManager
means that the fragment and its views will not properly save and restore their state.
The reason it fails with FragmentContainerView
is that FragmentContainerView
actually does the same FragmentTransaction
as you'd do normally.