Dagger 2.10 Android子组件和构建器

Dagger 2.10 Android子组件和构建器,android,dagger-2,Android,Dagger 2,使用新的(在2.10中)dagger.android类,我试图使用依赖于其他模块的子组件来注入东西,因此,有一个为这些模块提供setter的构建器。上的文档对此进行了描述,但不清楚如何实际编写和/或调用这些setter 从上述链接中引用: Injection()从应用程序获取DispatchingAndroidInjector,并将您的活动传递给Injection(activity)。DispatchingAndroidInjector查找活动类(即YourActivitySubcomponen

使用新的(在2.10中)dagger.android类,我试图使用依赖于其他模块的子组件来注入东西,因此,有一个为这些模块提供setter的构建器。上的文档对此进行了描述,但不清楚如何实际编写和/或调用这些setter

从上述链接中引用:

Injection()从应用程序获取DispatchingAndroidInjector,并将您的活动传递给Injection(activity)。DispatchingAndroidInjector查找活动类(即YourActivitySubcomponent.Builder)的AndroidInjector.Factory,创建AndroidInjector(即YourActivitySubcomponent),并将活动传递给Injector(YourActivity)

在我看来,为了能够为构建者调用setter,我需要在那里的某个地方确保构建者拥有所有必要的数据?我看到的问题是,在运行时,当Androidject调用为我的子组件生成的生成器时,我得到一个
非法状态异常:必须设置模块


所讨论的子组件实际上是一个片段,而不是一个活动,但我不确定这是否重要。关于如何做到这一点,您有什么想法吗?

简而言之,您应该在构建器(它是一个抽象类而不是一个接口)上提供您需要的其他模块

编辑:在此之前,请检查并确保您确实需要通过该模块。同样,如果你正在为你的Android类制作一个特定的模块,那么你可以依靠该类的自动注入来将配置或实例从图中拉出来。如果从模块中删除构造函数参数更容易,那么支持他的方法,因为这样可以避免不必要的实例和虚拟方法调用,从而提供更好的性能


首先,dagger.android在30秒内完成:活动(或片段)调用
AndroidInjection.injection(this)
,检查应用程序是否有
HasActivityInjector
(或
HasFragmentInjector
的父片段、活动和应用程序)。其思想是,您将绑定贡献给创建的多绑定
Map
,其中贡献的绑定几乎总是您编写的构建特定对象子组件的子组件构建器

AndroidInjection.inject(this)
AndroidInjector.Factory.create(T实例)可以看出
,您没有太多机会将特定于活动或特定于片段的详细信息传递给构建器。相反,您的子组件构建器会覆盖
seedInstance
实现。与
seedInstance
的文档一样:

提供要在生成的
androidject
的绑定图中使用的
实例
。默认情况下,该实例用作
绑定实例
方法,但可能会被重写以提供需要引用活动的任何模块

这应该是传递给
inject(Object)
的同一个实例

看起来是这样的:

@Subcomponent(modules = {OneModule.class, TwoModule.class})
public interface YourActivitySubcomponent extends AndroidInjector<YourActivity> {

  // inject(YourActivity) is inherited from AndroidInjector<YourActivity>

  @Builder
  public abstract class Builder extends AndroidInjector.Builder<YourActivity> {
    // Here are your required module builders:
    abstract Builder oneModule(OneModule module);
    abstract Builder twoModule(TwoModule module);

    // By overriding seedInstance, you don't let Dagger provide its
    // normal @BindsInstance implementation, but you can supply the
    // instance to modules or call your own BindsInstance:
    @Override public void seedInstance(YourActivity activity) {
      oneModule(new OneModule(activity));
      twoModule(new TwoModule(activity.getTwoModuleParameter()));
    }
  }
}

…但是如果你能做到这一点,那么你就可以更容易地处理这些绑定,方法是重写那些模块,实现一个零参数构造函数,它可以提供模块的构造函数参数,并让Dagger像创建任何具有公共零参数构造函数的模块一样创建这些参数。

这确实可行,但没有必要。种子Instance方法将活动实例提供到图中,因此您可以使用不带状态的MyActivityModule,只需在@provides方法中请求MyActivity

class MyActivityModule {
  @Provides
  static SomethingDerivedFromMyActivity providesMethod(MyActivity myActivity) {
    return myActivity.somethingDerived();
  }
}
这样做可以保存模块实例,并使生成的工厂更加精简


从。

看,它很可能会解决您的问题。您能发布一些简化的代码吗?您无法设置哪个模块?这完全奏效了!文档中没有提到它,但这使得使用dagger 2的新用户很难理解文档。+。不确定我的实现为什么会返回一个错误作为“错误:(154,5)错误:方法不重写或实现基于类MyActivityModule{@的超类型中的方法,
提供静态SomethingDerivedFromMyActivity providesMethod(MyActivity MyActivity){返回MyActivity.somethingDerived();}
足够好了。谢谢Damon!对你的答案发表了评论,并编辑了我的答案以包含指向你的答案的指针。你所说的“几乎都是子组件构建器”是什么意思?它们可以是子组件(构建器)以外的东西吗?+1:你(和我的同事Ron)当然,假设您的设置足够可重构,可以编辑模块以包含对您的活动的引用。如果您的模块来自第三方,或者设计用于除MyActivity之外的更多活动,那么您可能必须使用我更复杂的设置(文档中也建议使用该设置)。我回答这个问题时假设提问者需要有状态模块和构造函数,因为他们提到需要一个生成器,但如果你不这样做,那么当然可以更容易地表示。同意,但我的问题是,当使用你的解决方案时,编译器大声抗议“错误:(154,5)错误:方法未重写或实现超类型中的方法”。我已完全按照步骤进行操作,检查生成的代码后,我发现错误出现在
oneModule()的实现上
abstract方法。不确定为什么会发生这种情况,我正在使用dagger 2.10。无论如何,让我再做一些测试,也许我可以在我的代码中找到错误的地方。你能告诉我吗?听起来好像
oneModule
不是公共的或抽象的,或者类不是,或者诸如此类的。
class MyActivityModule {
  @Provides
  static SomethingDerivedFromMyActivity providesMethod(MyActivity myActivity) {
    return myActivity.somethingDerived();
  }
}