Android为多个Dagger2模块使用单个上下文

时间:2016-10-25 10:02:05

标签: android dependency-injection dagger-2

我是新手在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();

我该如何解决这个问题?

1 个答案:

答案 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);
}

同样,这些名字可以是任何东西。我个人并没有花很多心思去思考它们。希望这会有所帮助。