首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >组件中存在具有匹配键的dagger错误绑定

组件中存在具有匹配键的dagger错误绑定
EN

Stack Overflow用户
提问于 2021-11-03 08:07:05
回答 1查看 91关注 0票数 0

Dagger 2

代码语言:javascript
运行
复制
/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]

我有以下模块,其中包含这两个片段:

代码语言:javascript
运行
复制
@Module
abstract class FragmentProvider {
    @PerFragment
    @ContributesAndroidInjector(modules = [ProductListModule::class])
    abstract fun bindProductListV2Fragment(): ProductListV2Fragment
    
    @PerFragment
    @ContributesAndroidInjector(modules = [ProductListModule::class])
    abstract fun bindProductListFragment(): ProductListFragment
}

在我的ProductListModule中,我有以下内容:

代码语言:javascript
运行
复制
@Module
class ProductListModule {

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

fragmentManager将被注入到以下类中:

代码语言:javascript
运行
复制
class NewProductListPagerAdapter @Inject constructor(
    @ActivityContext private val context: Context,
    fragmentManager: FragmentManager
) { ..... }

这两个片段都会将这个NewProductListPagerAdapter注入其中。

代码语言:javascript
运行
复制
class ProductListV2Fragment  : BaseProductListFragment() {

    @Inject
    lateinit var mPagerAdapter: NewProductListPagerAdapter
}

class ProductListFragment  : BaseProductListFragment() {

    @Inject
    lateinit var mPagerAdapter: NewProductListPagerAdapter
}

我的AppComponent:

代码语言:javascript
运行
复制
@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)
}

====更新====

代码语言:javascript
运行
复制
@Module
abstract class FragmentProvider {

    @PerFragment
    @ContributesAndroidInjector(modules = [ProductListModule::class, ProductListBindingModule::class])
    abstract fun bindProductListFragment(): ProductListFragment


    @PerFragment
    @ContributesAndroidInjector(modules = [ProductListModule::class, ProductListV2BindingModule::class])
    abstract fun bindProductListV2Fragment(): ProductListV2Fragment
}

@Module
class ProductListModule {

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


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

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

堆栈跟踪在下面,这表明片段被多次绑定。原因是因为每个片段都注入了以下依赖:

代码语言:javascript
运行
复制
@Inject
lateinit var mPagerAdapter: NewProductListPagerAdapter

在NewProductListPagerAdapter构造函数中:

代码语言:javascript
运行
复制
class NewProductListPagerAdapter @Inject constructor(
    @ActivityContext private val context: Context,
    fragmentManager: FragmentManager
)

它需要提供FragmentManager;

代码语言:javascript
运行
复制
app/build/tmp/kapt3/stubs/uatDebug/tech/central/tops/di/AppComponent.java:22: error: [Dagger/DuplicateBindings] androidx.fragment.app.Fragment is bound multiple times:
public abstract interface AppComponent {
      @org.jetbrains.annotations.NotNull @Binds androidx.fragment.app.Fragment productlist.ProductListBindingModule.bindFragment(productlist.ProductListFragment)
      @org.jetbrains.annotations.NotNull @Binds androidx.fragment.app.Fragment productlist.ProductListV2BindingModule.bindFragment(productlist.ProductListV2Fragment)
      androidx.fragment.app.Fragment is injected at
          authentication.usecase.FacebookLoginUseCase(fragment, …)
      authentication.usecase.FacebookLoginUseCase is injected at
          authentication.usecase.SocialLoginUseCase(…, facebookLoginUseCase, …)
      authentication.usecase.SocialLoginUseCase is injected at
          authentication.FacebookLoginViewModel(…, socialLoginUseCase, …)
      authentication.FacebookLoginViewModel is injected at
          authentication.FacebookLoginViewModelModule.facebookViewModelChildFactory(facebookLoginViewModel)
      java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
          di.factory.ViewModelProviderFactory(classToViewModel)
      di.factory.ViewModelProviderFactory is injected at
          .authentication.login.LoginFragment.mViewModelChildFactory
      authentication.login.LoginFragment is injected at
          dagger.android.AndroidInjector.inject(T) [tech.central.tops.di.AppComponent → di.BuilderModule_BindMainActivity.MainActivitySubcomponent → FragmentProvider_BindLoginFragment.LoginFragmentSubcomponent]
EN

回答 1

Stack Overflow用户

发布于 2021-11-05 20:51:50

您的模块依赖于ProductListFragment来获取一个子FragmentManager。但是,相同模块也用于注入ProductListV2Fragment,此时没有可用的ProductListFragment

为了重用该模块,您需要将对ProductListFragment的依赖拆分为单独的模块。此模块应用于ProductListFragment,类似的模块应用于ProductListV2Fragment。在这些模块中,您可以直接提供FragmentManager,也可以将这两个片段绑定到一个公共超类,如FragmentBaseProductListFragment

如果将两个片段都绑定到Fragment,结果代码将如下所示:

代码语言:javascript
运行
复制
@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
}

至于错误消息本身,它告诉您三件事:

  • 生成的ProductListV2FragmentSubcomponent需要ProductListFragment,但它没有可用的绑定。
  • 该子组件可能能够将依赖项注入现有的ProductListFragment。这在其他情况下可能是有用的信息,但它与您正在尝试做的事情无关。
  • 您的应用程序中有一个组件可以提供ProductListFragment。具体地说,这是生成的ProductListFragmentSubcomponent,它在其工厂中接受一个ProductListFragment
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69821456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档