多个独立组分注入
Multiple independent component injection
我正在处理的 android 项目的匕首配置:
注意:我已经在需要的地方提供了所有需要的@Component、@Module、@Provides 注释。
MainActivity {
@Inject A a;
@Inject B b;
onCreate(){
ComponentX.inject(this);
ComponentY.inject(this);
}
}
ComponentX-> ModuleA ->providerA
ComponentY -> ModuleB -> providerB
如您所见,这是两个完全独立的组件,除了在注入点之外,在任何方面都不相关。
在编译过程中出现以下错误:
In file A.java
error: B cannot be provided without an @Provides- or @Produces-annotated method.
MainActivity.b
[injected field of type: B b]
我是不是误以为在使用 dagger 2 时可以使用多个组件,或者应用程序应该使用一个负责所有注入的大组件?
任何人都可以帮助我了解我哪里出错了吗?
is the application supposed to use one big component which takes care
of all the injections?
您可以使用 Subcomponent
。在您的情况下,组件声明将如下所示:
@Subcomponent(modules=ModuleB.class)
public interface ComponentY{
void inject(MainActivity mainActivity);
}
@Component(modules=ModuleA.class)
public interface ComponentX{
ComponentY plus(ModuleB module);
}
ComponentY
创作:creationCompunentY = ComponentX.plus(new ModuleB());
现在 MainActivity
你只打电话给 ComponentY.inject(this);
MainActivity {
@Inject A a;
@Inject B b;
onCreate(){
ComponentY.inject(this);
}
}
有关子组件的更多信息可以在 migration from Dagger1 guide (look at Subgraphs part), Subcomponent JavaDoc and Component JavaDoc 中找到(查看子组件部分)。
is the application supposed to use one big component
有点,你应该在范围内考虑它。对于给定的范围,只有一个组件。范围例如 ApplicationScope
、FragmentScope
(保留)、ActivityScope
、ViewScope
。对于每个范围,都有一个给定的组件;范围不在组件之间共享。
(这实际上意味着,如果你想在 @ApplicationScope
中拥有全局单例,则有一个应用程序范围的组件。如果你想要 activity-specific 类,然后为特定的 activity 创建一个组件,这将取决于应用程序范围的组件)。
请参阅@MyDogTom 以获取 @Subcomponent
注释,但您也可以使用组件依赖项来创建子范围组件。
@YScope
@Component(dependencies = ComponentX.class, modules=ModuleB.class)
public interface ComponentY extends ComponentX {
B b();
void inject(MainActivity mainActivity);
}
@XScope
@Component(modules=ModuleA.class)
public interface ComponentX{
A a();
}
ComponentY componentY = DaggerComponentY.builder().componentX(componentX).build();
您不必只有一个组件,有多种方法可以将它们模块化,但是您创建的每个对象或向其中注入值的每个对象都必须具有由单个组件提供的所有值。
重构代码的一种方法是让 ComponentY 依赖于 ComponentX,反之亦然,例如
@Component(dependencies = ComponentX.class)
interface ComponentY {
void inject(MainActivity activity);
}
或者如果 ComponentX 和 ComponentY 彼此完全正交,您可以创建第三个组件,比如 ComponentZ。
@Component(dependencies = {ComponentX.class, ComponentY.class})
interface ComponentZ {
void inject(MainActivity activity);
}
或者您可以重复使用这些模块,例如
@Component(modules = {ModuleA.class, ModuleB.class})
interface ComponentZ {
void inject(MainActivity activity);
}
您决定如何拆分它在很大程度上取决于您的代码结构。如果组件 X 和 Y 可见但模块不可见,则使用组件依赖项,因为它们(和模块依赖项)实际上是组件的实现细节。否则,如果模块可见,则简单地重用它们。
我不会为此使用作用域,因为它们实际上用于管理具有不同生命周期的对象,例如与特定用户关联的对象,其生命周期是从用户登录到注销的时间,或者特定请求的生命周期。如果它们确实有不同的生命周期,那么您正在考虑使用作用域和子组件。
我正在处理的 android 项目的匕首配置: 注意:我已经在需要的地方提供了所有需要的@Component、@Module、@Provides 注释。
MainActivity {
@Inject A a;
@Inject B b;
onCreate(){
ComponentX.inject(this);
ComponentY.inject(this);
}
}
ComponentX-> ModuleA ->providerA
ComponentY -> ModuleB -> providerB
如您所见,这是两个完全独立的组件,除了在注入点之外,在任何方面都不相关。
在编译过程中出现以下错误:
In file A.java
error: B cannot be provided without an @Provides- or @Produces-annotated method.
MainActivity.b
[injected field of type: B b]
我是不是误以为在使用 dagger 2 时可以使用多个组件,或者应用程序应该使用一个负责所有注入的大组件?
任何人都可以帮助我了解我哪里出错了吗?
is the application supposed to use one big component which takes care of all the injections?
您可以使用 Subcomponent
。在您的情况下,组件声明将如下所示:
@Subcomponent(modules=ModuleB.class)
public interface ComponentY{
void inject(MainActivity mainActivity);
}
@Component(modules=ModuleA.class)
public interface ComponentX{
ComponentY plus(ModuleB module);
}
ComponentY
创作:creationCompunentY = ComponentX.plus(new ModuleB());
现在 MainActivity
你只打电话给 ComponentY.inject(this);
MainActivity {
@Inject A a;
@Inject B b;
onCreate(){
ComponentY.inject(this);
}
}
有关子组件的更多信息可以在 migration from Dagger1 guide (look at Subgraphs part), Subcomponent JavaDoc and Component JavaDoc 中找到(查看子组件部分)。
is the application supposed to use one big component
有点,你应该在范围内考虑它。对于给定的范围,只有一个组件。范围例如 ApplicationScope
、FragmentScope
(保留)、ActivityScope
、ViewScope
。对于每个范围,都有一个给定的组件;范围不在组件之间共享。
(这实际上意味着,如果你想在 @ApplicationScope
中拥有全局单例,则有一个应用程序范围的组件。如果你想要 activity-specific 类,然后为特定的 activity 创建一个组件,这将取决于应用程序范围的组件)。
请参阅@MyDogTom 以获取 @Subcomponent
注释,但您也可以使用组件依赖项来创建子范围组件。
@YScope
@Component(dependencies = ComponentX.class, modules=ModuleB.class)
public interface ComponentY extends ComponentX {
B b();
void inject(MainActivity mainActivity);
}
@XScope
@Component(modules=ModuleA.class)
public interface ComponentX{
A a();
}
ComponentY componentY = DaggerComponentY.builder().componentX(componentX).build();
您不必只有一个组件,有多种方法可以将它们模块化,但是您创建的每个对象或向其中注入值的每个对象都必须具有由单个组件提供的所有值。
重构代码的一种方法是让 ComponentY 依赖于 ComponentX,反之亦然,例如
@Component(dependencies = ComponentX.class)
interface ComponentY {
void inject(MainActivity activity);
}
或者如果 ComponentX 和 ComponentY 彼此完全正交,您可以创建第三个组件,比如 ComponentZ。
@Component(dependencies = {ComponentX.class, ComponentY.class})
interface ComponentZ {
void inject(MainActivity activity);
}
或者您可以重复使用这些模块,例如
@Component(modules = {ModuleA.class, ModuleB.class})
interface ComponentZ {
void inject(MainActivity activity);
}
您决定如何拆分它在很大程度上取决于您的代码结构。如果组件 X 和 Y 可见但模块不可见,则使用组件依赖项,因为它们(和模块依赖项)实际上是组件的实现细节。否则,如果模块可见,则简单地重用它们。
我不会为此使用作用域,因为它们实际上用于管理具有不同生命周期的对象,例如与特定用户关联的对象,其生命周期是从用户登录到注销的时间,或者特定请求的生命周期。如果它们确实有不同的生命周期,那么您正在考虑使用作用域和子组件。