首页 > 解决方案 > 没有专用子组件的片段注入

问题描述

我正在尝试使用 android-dagger 从手动定义的子组件中注入一个片段:

@Component(modules = [
    AndroidSupportInjectionModule::class,
    AppModule::class,
    BuilderModule::class
])
interface AppComponent : AndroidInjector<App> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<App>()

    fun someComponent(): SomeComponent

}

@Subcomponent
interface SomeComponent {

    fun inject(fragment: SomeFragment)

}

执行失败:

IllegalArgumentException:没有注入器工厂绑定到类“SomeFragment”


但是,如果我创建一个用@ContributesAndroidInjector它注释的片段绑定,则可以正常执行。该文档指出,所有这些都是创建一个子组件。为什么我不能手动操作?


最小的工作项目可以在 github 上找到: https ://github.com/absimas/fragment-injection

标签: androiddagger-2dagger

解决方案


@ContributesAndroidInjector创建一个子组件,是的。文档没有再说什么,但他们没有断言这只会创建一个子组件;它还将它安装到为每个Map<Class, AndroidInjector.Factory> dagger.android的注入类型提供支持的多重绑定中。

您可以在 Dagger User's Guide的 Android 页面上看到此地图绑定的示例:

@Binds
@IntoMap
@FragmentKey(YourFragment.class)
abstract AndroidInjector.Factory<? extends Fragment>
    bindYourFragmentInjectorFactory(YourFragmentSubcomponent.Builder builder);

请注意,这期望您绑定 Builder,而不是 Component:dagger.android 期望您希望从子组件中访问 Fragment 实例,因此绑定是为了AndroidInjector.Factory<? extends Fragment>DispatchingAndroidInjector可以调用create(Fragment)。这被设计为兼容Subcomponent.Builder,但它确实需要您定义@Subcomponent.Builder扩展适配器的嵌套接口AndroidInjector.Builder。请原谅我对 Kotlin 问题的 Java:

/** No need for an explicit inject, because you must extend AndroidInjector. */
@Subcomponent
interface SomeComponent extends AndroidInjector<SomeFragment> {

  /**
   * This abstract class handles the final create(Fragment) method,
   * plus @BindsInstance.
   */
  @Subcomponent.Builder
  abstract class Builder extends AndroidInjector.Builder<SomeFragment> {}
}

编辑:我现在想到您的标题表明您不需要专用的子组件;除了使用手动定义而不是@ContributesAndroidInjector,如果你想要一个多片段子组件,那么你可能会遇到这个建议的一些麻烦:dagger.android 需要实现AndroidInjector<YourFragment>,并且由于擦除,你自己不能拥有一个类实现多个AndroidInjector<T>AndroidInjector.Builder<T>接口或抽象类。在这些情况下,您可能需要编写一个手动 AndroidInjector.Factory 实现来调用正确的具体inject方法。然而,为了创建一个整体的 Fragment 组件,这似乎需要做很多工作,因为最佳实践决定了 dagger.android 的默认值:每个 Fragment 都有一个小而特定的组件。


推荐阅读