Dagger 2.10 Android 子组件和构建器
Dagger 2.10 Android subcomponents and builders
使用新的(在 2.10 中)dagger.android 类,我正在尝试使用依赖于其他模块的子组件注入东西,因此,有一个带有 setter 的构建器模块。 https://google.github.io/dagger/android.html 上的文档对此进行了描述,但不清楚如何实际编写 and/or 调用这些设置器。
引用上面link:
AndroidInjection.inject() gets a DispatchingAndroidInjector from the Application and passes your activity to inject(Activity). The DispatchingAndroidInjector looks up the AndroidInjector.Factory for your activity’s class (which is YourActivitySubcomponent.Builder), creates the AndroidInjector (which is YourActivitySubcomponent), and passes your activity to inject(YourActivity).
在我看来,为了能够调用 Builder 的 setter,我需要进入某个地方并确保 Builder 拥有所有必要的数据?我看到的问题是,在运行时,当 AndroidInjector 调用为我的子组件生成的构建器时,我得到一个 IllegalStateException: MODULE must be set
。
有问题的子组件实际上是一个片段,而不是 Activity,但我不确定这是否重要。关于如何做到这一点有什么想法吗?
简而言之,您应该 override the call to seedInstance
在 Builder(它是一个抽象 class 而不是接口)上提供您需要的其他模块。
编辑:在你这样做之前,检查并确保你确实需要通过该模块。作为 ,如果你正在为你的 Android class 创建一个特定的模块,你可以依靠 class 的自动注入来从中提取配置或实例当时的图表。如果仅从模块中消除构造函数参数更容易,请支持他的方法,这也可能提供更好的性能,因为它们避免了不必要的实例和虚拟方法调用。
首先,dagger.android 在 30 秒内: 而不是让每个 Activity 或片段知道其父级,Activity(或Fragment) 调用 AndroidInjection.inject(this)
,检查 HasActivityInjector
的应用程序(或 activity 的父片段和 HasFragmentInjector
的应用程序)。这个想法是你为一个多绑定创建的Map<Class, AndroidInjector.Factory>
贡献一个绑定,其中贡献的绑定几乎总是你编写的构建对象特定子组件的子组件构建器。
从 AndroidInjection.inject(this)
和 AndroidInjector.Factory.create(T instance)
可以看出,您没有太多机会将 Activity 特定或片段特定的详细信息传递给您的构建器。相反,这个想法是您的子组件构建器覆盖 seedInstance
实现。正如 seedInstance
:
的文档
Provides instance
to be used in the binding graph of the built AndroidInjector
. By default, this is used as a BindsInstance
method, but it may be overridden to provide any modules which need a reference to the activity.
This should be the same instance that will be passed to 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()));
}
}
}
这里的假设是您需要等待模块的 activity
实例。如果没有,那么您还可以选择在绑定子组件时调用它们:
@Provides @IntoMap @ActivityKey(YourActivity.class)
AndroidInjector.Factory bindInjector(YourActivitySubcomponent.Builder builder) {
return builder
.oneModule(new OneModule(...))
.twoModule(new TwoModule(...));
}
...但是如果你能做到这一点,那么你可以更轻松地处理这些绑定,方法是覆盖这些模块,实现一个可以提供模块构造函数参数的零参数构造函数,并让 Dagger 创建这些正如它对任何具有 public 零参数构造函数的模块所做的那样。
确实有效,但没有必要。 seedInstance 方法将 activity 实例提供到图中,因此您可以拥有没有状态的 MyActivityModule,只需在 @Provides 方法中请求 MyActivity。
class MyActivityModule {
@Provides
static SomethingDerivedFromMyActivity providesMethod(MyActivity myActivity) {
return myActivity.somethingDerived();
}
}
这样做可以保存模块实例并使生成的工厂更精简。
使用新的(在 2.10 中)dagger.android 类,我正在尝试使用依赖于其他模块的子组件注入东西,因此,有一个带有 setter 的构建器模块。 https://google.github.io/dagger/android.html 上的文档对此进行了描述,但不清楚如何实际编写 and/or 调用这些设置器。
引用上面link:
AndroidInjection.inject() gets a DispatchingAndroidInjector from the Application and passes your activity to inject(Activity). The DispatchingAndroidInjector looks up the AndroidInjector.Factory for your activity’s class (which is YourActivitySubcomponent.Builder), creates the AndroidInjector (which is YourActivitySubcomponent), and passes your activity to inject(YourActivity).
在我看来,为了能够调用 Builder 的 setter,我需要进入某个地方并确保 Builder 拥有所有必要的数据?我看到的问题是,在运行时,当 AndroidInjector 调用为我的子组件生成的构建器时,我得到一个 IllegalStateException: MODULE must be set
。
有问题的子组件实际上是一个片段,而不是 Activity,但我不确定这是否重要。关于如何做到这一点有什么想法吗?
简而言之,您应该 override the call to seedInstance
在 Builder(它是一个抽象 class 而不是接口)上提供您需要的其他模块。
编辑:在你这样做之前,检查并确保你确实需要通过该模块。作为
首先,dagger.android 在 30 秒内: 而不是让每个 Activity 或片段知道其父级,Activity(或Fragment) 调用 AndroidInjection.inject(this)
,检查 HasActivityInjector
的应用程序(或 activity 的父片段和 HasFragmentInjector
的应用程序)。这个想法是你为一个多绑定创建的Map<Class, AndroidInjector.Factory>
贡献一个绑定,其中贡献的绑定几乎总是你编写的构建对象特定子组件的子组件构建器。
从 AndroidInjection.inject(this)
和 AndroidInjector.Factory.create(T instance)
可以看出,您没有太多机会将 Activity 特定或片段特定的详细信息传递给您的构建器。相反,这个想法是您的子组件构建器覆盖 seedInstance
实现。正如 seedInstance
:
Provides
instance
to be used in the binding graph of the builtAndroidInjector
. By default, this is used as aBindsInstance
method, but it may be overridden to provide any modules which need a reference to the activity.This should be the same instance that will be passed to
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()));
}
}
}
这里的假设是您需要等待模块的 activity
实例。如果没有,那么您还可以选择在绑定子组件时调用它们:
@Provides @IntoMap @ActivityKey(YourActivity.class)
AndroidInjector.Factory bindInjector(YourActivitySubcomponent.Builder builder) {
return builder
.oneModule(new OneModule(...))
.twoModule(new TwoModule(...));
}
...但是如果你能做到这一点,那么你可以更轻松地处理这些绑定,方法是覆盖这些模块,实现一个可以提供模块构造函数参数的零参数构造函数,并让 Dagger 创建这些正如它对任何具有 public 零参数构造函数的模块所做的那样。
确实有效,但没有必要。 seedInstance 方法将 activity 实例提供到图中,因此您可以拥有没有状态的 MyActivityModule,只需在 @Provides 方法中请求 MyActivity。
class MyActivityModule {
@Provides
static SomethingDerivedFromMyActivity providesMethod(MyActivity myActivity) {
return myActivity.somethingDerived();
}
}
这样做可以保存模块实例并使生成的工厂更精简。