简体   繁体   English

组件中存在带有匹配键的 Dagger 错误绑定

[英]dagger error binding with matching key exists in component

Dagger 2匕首 2

/di/AppComponent.java:19: error: [Dagger/MissingBinding] ProductListFragment cannot be provided without an @Inject constructor or an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.
public abstract interface AppComponent {
                ^
  A binding with matching key exists in component: MainFragmentProvider_BindProductListFragment.ProductListFragmentSubcomponent
      ProductListFragment is injected at
          productlist.ProductListModule.provideChildFragmentManager(productListFragment)
      androidx.fragment.app.FragmentManager is injected at
          productlist.adapter.NewProductListPagerAdapter(…, fragmentManager)
      productlist.adapter.NewProductListPagerAdapter is injected at
          productlist.ProductListV2Fragment.mPagerAdapter
      productlist.ProductListV2Fragment is injected at
          dagger.android.AndroidInjector.inject(T) [di.AppComponent → di.BuilderModule_BindMainActivity.MainActivitySubcomponent →  MainFragmentProvider_BindProductListV2Fragment.ProductListV2FragmentSubcomponent]

I have the following module with these 2 fragments here:我有以下带有这 2 个片段的模块:

@Module
abstract class FragmentProvider {
    @PerFragment
    @ContributesAndroidInjector(modules = [ProductListModule::class])
    abstract fun bindProductListV2Fragment(): ProductListV2Fragment
    
    @PerFragment
    @ContributesAndroidInjector(modules = [ProductListModule::class])
    abstract fun bindProductListFragment(): ProductListFragment
}

In my ProductListModule I have the following:在我的 ProductListModule 中,我有以下内容:

@Module
class ProductListModule {

    @Provides
    fun provideChildFragmentManager(productListFragment: ProductListFragment) =
        productListFragment.childFragmentManager
}

The fragmentManager will be injected into the following class: fragmentManager 将被注入到以下类中:

class NewProductListPagerAdapter @Inject constructor(
    @ActivityContext private val context: Context,
    fragmentManager: FragmentManager
) { ..... }

And both fragments will inject this NewProductListPagerAdapter in them.两个片段都会在其中注入这个 NewProductListPagerAdapter。

class ProductListV2Fragment  : BaseProductListFragment() {

    @Inject
    lateinit var mPagerAdapter: NewProductListPagerAdapter
}

class ProductListFragment  : BaseProductListFragment() {

    @Inject
    lateinit var mPagerAdapter: NewProductListPagerAdapter
}

My AppComponent:我的应用组件:

@Singleton
@Component(
    modules = [
        AndroidSupportInjectionModule::class,
        AppModule::class,
        ProductModule::class,
        BaseAppModule::class
    ]
)
interface AppComponent {
    @Component.Factory
    interface Factory {
        fun create(
            @BindsInstance application: Application,
        ): AppComponent
    }

    fun inject(tsApplication: TsApplication)
}

Your module depends on ProductListFragment to obtain a child FragmentManager .您的模块依赖ProductListFragment来获取子FragmentManager However, that same module is used to inject into ProductListV2Fragment , and there is no ProductListFragment available at that point.但是,相同的模块用于注入ProductListV2Fragment ,并且此时没有可用的ProductListFragment

In order to reuse that module, you will need to split the dependency on ProductListFragment into a separate module.为了重用该模块,您需要将ProductListFragment的依赖拆分为一个单独的模块。 This module should be used for ProductListFragment , and a similar module should be used for ProductListV2Fragment .此模块应用于ProductListFragment ,而类似的模块应用于ProductListV2Fragment In these modules, you can either provide FragmentManager directly or bind both fragments to a common superclass such as Fragment or BaseProductListFragment .在这些模块中,您可以直接提供FragmentManager或将两个片段绑定到一个公共超类,例如FragmentBaseProductListFragment

If you bind both fragments to Fragment , the resulting code will look like this:如果将两个片段都绑定到Fragment ,则生成的代码将如下所示:

@Module
abstract class FragmentProvider {
    @PerFragment
    @ContributesAndroidInjector(modules = [
        ProductListModule::class,
        ProductListV2BindingModule::class
    ])
    abstract fun bindProductListV2Fragment(): ProductListV2Fragment
    
    @PerFragment
    @ContributesAndroidInjector(modules = [
        ProductListModule::class,
        ProductListBindingModule::class
    ])
    abstract fun bindProductListFragment(): ProductListFragment
}

@Module
class ProductListModule {

    @Provides
    fun provideChildFragmentManager(productListFragment: Fragment) =
        productListFragment.childFragmentManager
}

@Module
abstract class ProductListBindingModule {
    @Binds
    fun bindFragment(fragment: ProductListFragment): Fragment
}

@Module
abstract class ProductListV2BindingModule {
    @Binds
    fun bindFragment(fragment: ProductListV2Fragment): Fragment
}

As for the error message itself, it tells you three things:至于错误消息本身,它告诉您三件事:

  • The generated ProductListV2FragmentSubcomponent requires a ProductListFragment , but there is no available binding for it.生成的ProductListV2FragmentSubcomponent需要ProductListFragment ,但没有可用的绑定。
  • The subcomponent may be able to inject dependencies into an existing ProductListFragment .子组件可能能够将依赖项注入到现有的ProductListFragment This can be useful information in other situations, but it isn't relevant to what you're trying to do.这在其他情况下可能是有用的信息,但与您尝试执行的操作无关。
  • There is a component in your app which can provide ProductListFragment .您的应用中有一个组件可以提供ProductListFragment Specifically, this is the generated ProductListFragmentSubcomponent , which takes a ProductListFragment in its factory.具体来说,这是生成的ProductListFragmentSubcomponent ,它在其工厂中采用ProductListFragment

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM