我是新手在android上使用Dagger2
。我创建了一些类作为Dagger模块,他们正在使用context
,我无法合并,组合或使用单个上下文用于他们需要的其他模块。我现在得到这个错误:
android.content.Context is bound multiple times
SpModules:
@Module
public class SpModules {
private Context context;
public SpModules(Context context) {
this.context = context;
}
@Provides // this can be non-scoped because anyway the same instance is always returned
Context provideContext() {
return this.context;
}
@Provides
@Singleton
SP provideSharePreferences(Context context) {
return new SP(context); // use method-local Context
}
}
RealmModule
:
@Module
public class RealmModule {
private Context context;
@Provides
Context provideApplicationContext() {
return AlachiqApplication.getInstance();
}
@Provides
@Singleton
RealmConfiguration provideRealmConfiguration() {
final RealmConfiguration.Builder builder = new RealmConfiguration.Builder()
.schemaVersion(Migration.SCHEMA_VERSION)
.deleteRealmIfMigrationNeeded()
.migration(new Migration());
return builder.build();
}
@Provides
Realm provideDefaultRealm(RealmConfiguration config) {
return Realm.getInstance(config);
}
@Provides
Context provideContext() {
return this.context;
}
}
组件:
@Component(modules = {RealmModule.class, SpModules.class})
@Singleton
public interface ApplicationComponent {
void inject(ActivityRegister target);
void inject(ActivityMain target);
void inject(ActivityBase target);
void inject(FragmentAlachiqChannels target);
void inject(SocketServiceProvider target);
}
然后使用Application类来制作Dagger2:
component = DaggerApplicationComponent.builder()
.appModules(new SpModules(this))
.build();
我该如何解决这个问题?
答案 0 :(得分:4)
这只是匕首告诉你,你为你的组件提供了几次相同的类。实际上,您可以在此处以及在同一组件的不同模块中执行此操作:
@Provides
Context provideApplicationContext() {
return AlachiqApplication.getInstance();
}
@Provides
Context provideContext() {
return this.context;
}
这些方法不同,但它们提供相同的依赖关系,没有额外的信息,匕首无法确定使用哪个Context
。
你有几个选择。如果单个上下文足以为您的所有类提供服务,那么您可以简单地删除额外的提供方法。
但是,我们假设您需要应用程序和其他一些上下文。您可以使用注释Named
。在这里它是如何工作的,你用这个注释注释你的提供方法,它基本上会给依赖项命名。像这样:
@Module
public class SpModules {
// ...
@Provides
@Named("context")
Context provideContext() {
return this.context;
}
//...
}
@Module
public class RealmModule {
//...
@Provides
@Named("application.context")
Context provideApplicationContext() {
return AlachiqApplication.getInstance();
}
//...
}
现在,您还需要在使用这些依赖项时进行注释,例如,假设您有一个依赖于应用程序上下文的对象:
public class Something {
public Something(@Named("application.context") Context context) {
//...
}
}
或作为一个领域:
public class Something {
@Named("application.context") Context context;
// ...
}
甚至在您的模块中:
@Provides
@Singleton
SP provideSharePreferences(@Named("context") Context context) {
return new SP(context);
}
名称可以是您想要的任何名称,只要它们一致。
另一种方法是使用Qualifiers
。它们的工作方式与Named
注释类似,但不同。您将对依赖项进行资格认证。所以说你创建了两个限定符:
@java.lang.annotation.Documented
@java.lang.annotation.Retention(RUNTIME)
@javax.inject.Qualifier
public @interface InstanceContext {
}
@java.lang.annotation.Documented
@java.lang.annotation.Retention(RUNTIME)
@javax.inject.Qualifier
public @interface ApplicationContext {
}
然后,您可以使用这些来注释提供方法:
@Module
public class SpModules {
// ...
@Provides
@InstanceContext
Context provideContext() {
return this.context;
}
//...
}
@Module
public class RealmModule {
//...
@Provides
@ApplicationContext
Context provideApplicationContext() {
return AlachiqApplication.getInstance();
}
//...
}
然后以与名称相同的方式使用它。以下是示例:
public class Something {
public Something(@ApplicationContext Context context) {
//...
}
}
public class Something {
@ApplicationContext Context context;
// ...
}
@Provides
@Singleton
SP provideSharePreferences(@InstanceContext Context context) {
return new SP(context);
}
同样,这些名字可以是任何东西。我个人并没有花很多心思去思考它们。希望这会有所帮助。