gpt4 book ai didi

android - Dagger2 : How no to duplicate Module-Component forActivity/Fragments, 依赖单个 Base(Module/Component) 作为 Base(Activity/Fragment) &

转载 作者:行者123 更新时间:2023-12-02 02:56:19 27 4
gpt4 key购买 nike

给定 BaseFragment 及其子类:DerivedFragmentA、DerivedFragmentB、...

假设,大多数 @Inject 字段对于每个 fragment 都是通用的,因此在 BaseFragment 中声明:

abstract class BaseFragment : DaggerFragment() {
@Inject lateinit var vmFactory: ViewModelProvider.Factory
}

class DerivedFragmentA : BaseFragment()
class DerivedFragmentB : BaseFragment()
...

对于每个派生 fragment ,我们必须手动创建模块-组件对,例如:

@Subcomponent
interface DerivedFragmentAComponent : AndroidInjector<DerivedFragmentA> {

@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<DerivedFragmentA>()
}

@Module(subcomponents = [DerivedFragmentAComponent::class])
abstract class DerivedFragmentAModule {

@Binds @IntoMap @FragmentKey(DerivedFragmentA::class)
abstract fun bind(builder: DerivedFragmentAComponent.Builder): AndroidInjector.Factory<out Fragment>
}

然后将它们中的每一个安装到某个外部组件,就像这样:

@Subcomponent(modules = [DerivedFragmentAModule::class, DerivedFragmentBModule::class, ...])
interface MainComponent : AndroidInjector<MainActivity> {

@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainActivity>()
}

但这是一种样板。

如果我们尝试为 BaseFragment 只创建一个模块组件并将其安装到 MainComponent - 我们将在调用 AndroidInjector.inject(fragment) 方法期间遇到运行时异常,使用以下消息:

  "No injector factory bound for Class<DerivedFragmentA>. Injector factories were bound for supertypes of DerivedFragmentA: BaseFragment. Did you mean to bind an injector factory for the subtype?"

有没有办法解决这个问题并避免代码重复?或者由于 Dagger-2 强烈依赖类名,它的 impossible

最佳答案

Dagger 2 的注入(inject)始终适用于您指定的类型。 inject(fragment : BaseFragment)只会注入(inject) BaseFragment 的字段并且没有在任何子类中声明的字段。这是您必须牢记的一点。

你说你只想声明一个组件并将东西注入(inject)到 BaseFragment 中只是,这正是您可以做的。而不是为您的 DerivedFragment 创建子组件你为你的 BaseFragment 创建一个...

@Subcomponent
interface BaseFragmentComponent : AndroidInjector<BaseFragment> {

@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<BaseFragment>()
}

然后你可以绑定(bind)BaseFragment.Builder给你的DerivedFragmentX

@Module(subcomponents = [BaseFragmentComponent::class])
abstract class BaseFragmentModule {

@Binds @IntoMap @FragmentKey(DerivedFragmentA::class)
abstract fun bind(builder: BaseFragmentComponent.Builder): AndroidInjector.Factory<out Fragment>

@Binds @IntoMap @FragmentKey(DerivedFragmentB::class)
abstract fun bind(builder: BaseFragmentComponent.Builder): AndroidInjector.Factory<out Fragment>

@Binds @IntoMap @FragmentKey(DerivedFragmentC::class)
abstract fun bind(builder: BaseFragmentComponent.Builder): AndroidInjector.Factory<out Fragment>
}

重要的一点是设置@FragmentKey(DerivedFragmentA::class)引用子类,因为这是 Dagger 在调用 AndroidInjection.inject(fragment) 时会查找的对象.


我仍然建议您不要使用这种方法,因为您最终会混合使用一些完全注入(inject)的 fragment 和仅注入(inject) BaseFragment 的其他 fragment 。这听起来让我感到困惑。

你可以只使用 @ContributesAndroidInjector 而是为您生成样板代码并正确注入(inject)每个 fragment 。

关于android - Dagger2 : How no to duplicate Module-Component forActivity/Fragments, 依赖单个 Base(Module/Component) 作为 Base(Activity/Fragment) &,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49153037/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com