Dagger2: no injector factory bound for fragment

There could be other scenarious, where I got similar errors:

Possible case 1:
When you have a DialogFragment shown from a Fragment.
It's important to use the same FragmentManager.

For instance you have a "fragment-scoped screen":

@FragmentScope
@ContributesAndroidInjector(modules = [HomeInjectors::class])
abstract fun provideHomeFragment() HomeFragment

With a subcomponent

@Module
abstract class HomeInjectors {

    @ChildFragmentScope
    @ContributesAndroidInjector(modules = [DetailsModule::class])
    abstract fun provideDetailsFragment(): DetailsDialogFragment

}

Important here to note, that when you show a dialog fragment, you should use child fragment manager not the Activity's one.

in this case, if you show dialog from the HomeFragment,

detailsDialog.show(activity.supportFragmentManager, "some tag)

and

detailsDialog.show(requireFragmentManager(), "some tag)

will not work.

You should do instead:

detailsDialog.show(childFragmentManager, "some tag)

Possible case 2: Parent fragment with child fragments.

In order to make child fragments with "smaller" scope (Sample code is the same as above, but consider DetailsDialogFragment a regular fragment and a child of the HomeFragment).

In my case, the child fragment wasn't able to find Parent's fragment injector.

The reason was that while providing a child fragment injector, I mistakenly made my BaseFragment implement HasFragmentInjector.
However, since I use support fragments (AndroidX or whatever), I should have made BaseFragment implement HasSupportFragmentInjector

So the BaseFragment may look like:

import androidx.fragment.app.Fragment

abstract class BaseFragment : SometFragment(), HasSupportFragmentInjector {

    @Inject lateinit var childFragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun supportFragmentInjector(): AndroidInjector<Fragment> {
        return childFragmentInjector
    }

    override fun onAttach(context: Context) {
        AndroidSupportInjection.inject(this)
        super.onAttach(context)
    }
}

It is useful when by certain reasons your "BaseFragment" must have other than DaggerFragment parent


When you inject using AndroidSupportInjection.inject(this) from your HomeFragment, Dagger will walk the parent-fragment hierarchy to find someone that implements HasSupportFragmentInjector. To make it work, make your MainActivity extends DaggerAppCompatActivity which implements HasSupportFragmentInjector.

From the doc of AndroidSupportInjection.inject(Fragment fragment):

Injects {@code fragment} if an associated {@link dagger.android.AndroidInjector} implementation can be found, otherwise throws an {@link IllegalArgumentException}.

Uses the following algorithm to find the appropriate {@code AndroidInjector} to use to inject {@code fragment}:

  1. Walks the parent-fragment hierarchy to find the a fragment that implements {@link HasSupportFragmentInjector}, and if none do
  2. Uses the {@code fragment}'s {@link Fragment#getActivity() activity} if it implements {@link HasSupportFragmentInjector}, and if not
  3. Uses the {@link android.app.Application} if it implements {@link HasSupportFragmentInjector}.

If none of them implement {@link HasSupportFragmentInjector}, a {@link IllegalArgumentException} is thrown.

@throws IllegalArgumentException if no parent fragment, activity, or application implements {@link HasSupportFragmentInjector}.

With this, Dagger will use

@FragmentScope
@ContributesAndroidInjector
abstract HomeFragment provideHomeFragment();

from your MainActivityModule to inject inside your HomeFragment.