Dagger2: no injector factory bound for fragment

后端 未结 3 808
孤独总比滥情好
孤独总比滥情好 2021-01-04 05:44

I\'m trying to convert a project that I\'m building to use the dagger-android API for the DI framework, but I\'m running into a dead end with an IllegalArgumentException whe

相关标签:
3条回答
  • 2021-01-04 06:09

    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

    0 讨论(0)
  • 2021-01-04 06:23

    in my case, I did not define the Fragment in @Module class! so When I added it like :

    @ActivityScope
    @ContributesAndroidInjector(modules = {ActivityModule.class})
    abstract InvestmentDetailsFragment bindInvestmentDetailsFragment();
    

    my problem fixed!

    0 讨论(0)
  • 2021-01-04 06:28

    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.

    0 讨论(0)
提交回复
热议问题