Search code examples
androidandroid-fragmentsandroid-fragment-manager

FragmentContainerView in ViewHolder - which is the appropriate FragmentManager?


I am including a fragment in a row for a RecyclerView - I know it is not the most recommended thing to do, but it is not used much and I would like it as a Fragment as we are using it multiple places.

I have added this in the view for the ViewHolder:

<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/productRecommendationSectionFragment"
    android:name="dk.xxx.ui.sections.productRecommendation.ProductRecommendationSectionFragment"
    android:layout_width="match_parent"
    android:tag="ProductRecommendationSectionFragment"
    android:layout_height="wrap_content" />

It loads fine as expected but the question is then how to access the correct FragmentManager to configure the fragment?

The documentation states that it ".. add the Fragment to the appropriate FragmentManager" and you should be able to access it by the tag.

But it does not seems to be either the contraining Fragment´ Fragment.fragmentManager or Fragment.childFragmentManager, nor the Activity.fragmentManager. (Tested by a delegate to Containing Fragment)

Which could it then be?

One clue could be that in the ViewHolder calling binding.root.findFragment<ContainingFragment>() resulting in IllegalStateException:

"View androidx.fragment.app.FragmentContainerView... app:id/productRecommendationSectionFragment} does not have a Fragment set"

Edit:

I have tried those fragment managers from the containing fragment through a delegate.

activity!!.supportFragmentManager.findFragmentByTag("ProductRecommendationSectionFragment") // null
childFragmentManager.findFragmentByTag("ProductRecommendationSectionFragment") // null
fragmentManager.findFragmentByTag("ProductRecommendationSectionFragment") // null

Solution

  • After some debugging in FragmentContainerView itself, I have hopefully found all the cases of the FragmentManager used whilst adding a fragment via the android:name attribute.

    • Fragments in the activity view hierarchy (from Activity.setContentView(Int)): Activity.getSupportFragmentManager()

    • Fragments in another fragments hierarchy (from Fragment.onCreateView(...)): Fragment.getChildFragmentManager

    • Fragments in a RecyclerView row, where the RecyclerView is either in a Fragment or an Activity: Activity.getSupportFragmentManager()

    Now the first two are well documented and not of interest here, but I found the third case to be surprising, especially as it doesn't seem to make a difference what the RecyclerView has been inflated into. If I had to take a guess of why this is, it would probably be in onCreateViewHolder.When you inflate your row you pass false into the inflate function's attachToRoot, so as the FragmentContainerView is not attached to a parent when it is initialised, it has to use the highest level fragment manager - from the activity. However this is just speculation.

    Regardless, in answer to your question - it is definitely the activities fragment manager.


    You also said that you have tried using all the fragment managers anyway and they all couldn't find your fragment, but I wasn't able to replicate this problem. I managed to find my fragment in the RecyclerView just fine so I would expect there's something else going on that we can't find from the code you've shown, in theory it works.