Dagger - 在不同的组件上获取相同的实例
Dagger - Getting Same Instance On Different Component
我遇到了与 问题类似的问题。
虽然接受的答案确实有帮助,但我缺少解决问题的最后一部分。
我有 2 个 android 库模块:common
和 exp
这取决于 common
.
common
下的所有内容:
@Module
public class CommonModule {
@Singleton
@Provides
public Repository providesRepository() {
return new Repository();
}
}
@Singleton
@Component(modules={CommonModule.class})
public interface CommonComponent {
void inject(CommonClass commonClass);
/**
CommonClass needs instance of Repository
**/
}
public class CommonDIHolder {
public static CommonComponent sComponent;
public static void init() {
sComponent = DaggerCommonComponent.builder().build();
}
}
exp
下的所有内容:
@Module(includes={CommonModule.class})
public class ExpModule {
@Singleton
@Provides
public ExpResource provideExpResource() {
return new ExpResource();
}
}
@Singleton
@Component(modules={ExpModule.class}, dependencies={CommonComponent.class})
public interface ExpComponent {
void inject(ExpClass expClass);
/**
ExpClass needs instance of Repository and ExpResource
**/
}
public class ExpDIHolder {
public static ExpComponent sComponent;
public static void init() {
sComponent = DaggerExpComponent.builder()
.commonComponent(CommonDIHolder.sComponent)
.build();
}
}
我需要 CommonClass
和 ExpClass
接收相同的 Repository
实例。
这种方法的问题是 @Singleton
不能依赖于 @Singleton
。所以我必须将 ExpComponent
的范围更改为名为 @ExpScope
的自定义范围。然后我也将 provideExpResource
更改为 @ExpScope
。
然后我遇到一个错误,说 ExpComponent
可能不会引用不同范围的绑定。它指的是 provideRepository
具有不同的范围 (@Singleton
)。如果我将范围更改为 ExpScope
,那么 CommonComponent
将具有与 provideRepository
不同的范围。
如果我将所有 @Singleton
更改为 @ExpScope
,那么我会收到此错误消息:depends on scoped components in a non-hierarchical scope ordering
我该怎么办?或者我在这里做错了方法?
只使用一个 @Singleton
作用域组件
你应该有一个并且只有一个 @Singleton
作用域组件是这样的:
@Singleton
@Component(modules={CommonModule.class, ExpModule.class})
public interface CommonComponent {
}
仅指定活动、片段和服务作为组件的显式注入目标
在 Android 应用程序中,您应该只将 Activity、Fragments 和 Services 列为注入站点。您应该配置 Dagger 2 以注入其余的依赖项,而不必诉诸于在它们内部调用 component.inject(this)
。
例如,如果您的 CommonClass
看起来像这样:
public class CommonClass {
@Inject Repository repository;
public class CommonClass() {
CommonComponentHolder.get().inject(this);
}
}
重构如下:
public class CommonClass {
private final Repository repository;
@Inject
public class CommonClass(Repository repository) {
this.repository = repository;
}
}
现在,当您有一个 Activity 或需要 CommonClass
的片段并且您正在注入 CommonComponent
或其子组件或依赖组件之一时,它们可以获得实例CommonClass
连接了正确的依赖项:
public class MyActivity extends AppCompatActivity {
@Inject CommonClass commonClass;
public void onCreate(Bundle savedInstanceState) {
CommonComponentHolder.getComponent().inject(this);
}
}
使用子组件或依赖组件指定注入目标
现在您有一个 @Singleton
范围的组件,您可能想要为您的 Activity 或 Fragment 创建一个范围更窄的组件。您必须将它连接到您的 CommonComponent
,因此使用依赖组件或子组件(从 Dagger 2.10 开始首选子组件)。既然你说你已经尝试过定义一个 @ExpScope
,我认为缺少的部分是使用注入你的 Activity 或片段的 @ExpScope
制作子组件或依赖组件。
顶级单例组件类似于以下内容:
@Singleton
@Component(modules={CommonModule.class, ExpModule.class})
public interface CommonComponent {
ExpComponent.Builder exComponent();
}
然后对于子组件:
@ExpScope
@Subcomponent(modules = {NarrowerScopedModule.class})
public interface ExpComponent {
@Subcomponent.Builder
public interface Builder {
Builder narrowerScopedModule(NarrowerScopedModule narrowerScopedModule);
ExpComponent build();
}
}
中有 Android 个项目的良好工作示例
我遇到了与
我有 2 个 android 库模块:common
和 exp
这取决于 common
.
common
下的所有内容:
@Module
public class CommonModule {
@Singleton
@Provides
public Repository providesRepository() {
return new Repository();
}
}
@Singleton
@Component(modules={CommonModule.class})
public interface CommonComponent {
void inject(CommonClass commonClass);
/**
CommonClass needs instance of Repository
**/
}
public class CommonDIHolder {
public static CommonComponent sComponent;
public static void init() {
sComponent = DaggerCommonComponent.builder().build();
}
}
exp
下的所有内容:
@Module(includes={CommonModule.class})
public class ExpModule {
@Singleton
@Provides
public ExpResource provideExpResource() {
return new ExpResource();
}
}
@Singleton
@Component(modules={ExpModule.class}, dependencies={CommonComponent.class})
public interface ExpComponent {
void inject(ExpClass expClass);
/**
ExpClass needs instance of Repository and ExpResource
**/
}
public class ExpDIHolder {
public static ExpComponent sComponent;
public static void init() {
sComponent = DaggerExpComponent.builder()
.commonComponent(CommonDIHolder.sComponent)
.build();
}
}
我需要 CommonClass
和 ExpClass
接收相同的 Repository
实例。
这种方法的问题是 @Singleton
不能依赖于 @Singleton
。所以我必须将 ExpComponent
的范围更改为名为 @ExpScope
的自定义范围。然后我也将 provideExpResource
更改为 @ExpScope
。
然后我遇到一个错误,说 ExpComponent
可能不会引用不同范围的绑定。它指的是 provideRepository
具有不同的范围 (@Singleton
)。如果我将范围更改为 ExpScope
,那么 CommonComponent
将具有与 provideRepository
不同的范围。
如果我将所有 @Singleton
更改为 @ExpScope
,那么我会收到此错误消息:depends on scoped components in a non-hierarchical scope ordering
我该怎么办?或者我在这里做错了方法?
只使用一个 @Singleton
作用域组件
你应该有一个并且只有一个 @Singleton
作用域组件是这样的:
@Singleton
@Component(modules={CommonModule.class, ExpModule.class})
public interface CommonComponent {
}
仅指定活动、片段和服务作为组件的显式注入目标
在 Android 应用程序中,您应该只将 Activity、Fragments 和 Services 列为注入站点。您应该配置 Dagger 2 以注入其余的依赖项,而不必诉诸于在它们内部调用 component.inject(this)
。
例如,如果您的 CommonClass
看起来像这样:
public class CommonClass {
@Inject Repository repository;
public class CommonClass() {
CommonComponentHolder.get().inject(this);
}
}
重构如下:
public class CommonClass {
private final Repository repository;
@Inject
public class CommonClass(Repository repository) {
this.repository = repository;
}
}
现在,当您有一个 Activity 或需要 CommonClass
的片段并且您正在注入 CommonComponent
或其子组件或依赖组件之一时,它们可以获得实例CommonClass
连接了正确的依赖项:
public class MyActivity extends AppCompatActivity {
@Inject CommonClass commonClass;
public void onCreate(Bundle savedInstanceState) {
CommonComponentHolder.getComponent().inject(this);
}
}
使用子组件或依赖组件指定注入目标
现在您有一个 @Singleton
范围的组件,您可能想要为您的 Activity 或 Fragment 创建一个范围更窄的组件。您必须将它连接到您的 CommonComponent
,因此使用依赖组件或子组件(从 Dagger 2.10 开始首选子组件)。既然你说你已经尝试过定义一个 @ExpScope
,我认为缺少的部分是使用注入你的 Activity 或片段的 @ExpScope
制作子组件或依赖组件。
顶级单例组件类似于以下内容:
@Singleton
@Component(modules={CommonModule.class, ExpModule.class})
public interface CommonComponent {
ExpComponent.Builder exComponent();
}
然后对于子组件:
@ExpScope
@Subcomponent(modules = {NarrowerScopedModule.class})
public interface ExpComponent {
@Subcomponent.Builder
public interface Builder {
Builder narrowerScopedModule(NarrowerScopedModule narrowerScopedModule);
ExpComponent build();
}
}
中有 Android 个项目的良好工作示例