2016-10-25 12 views
4

私はアンドロイドでDagger2を使用する初心者です。私はcontextを使用しているDaggerモジュールとしていくつかのクラスを作成します。それらを必要とする他のモジュールにマージ、結合、または単一のコンテキストを使用することはできません。そして私は今、このエラーが出る:Android複数のDagger2モジュールに単一のコンテキストを使用

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(); 

どうすればこの問題を解決できますか?

答えて

3

これは、あなたがコンポーネントに同じクラスを何度か提供していることを伝える単純なものです。実際には、あなたは、同じコンポーネントのためにここだけでなく、異なるモジュール間でそれを行う:

@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) { 
    //... 
    } 
} 

やフィールドなど:

@Provides 
@Singleton 
SP provideSharePreferences(@Named("context") Context context) { 
    return new SP(context); 
} 
public class Something { 
    @Named("application.context") Context context; 
    // ... 
} 

あるいはあなたのモジュールで

名前は一貫していれば何でも構いません。

代替方法はQualifiersです。それらは、Named注釈と似ていますが、異なっています。あなたは依存関係を修飾します。ですから、2つの修飾子を作成すると言う:

@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); 
} 

これらの名前もまた何でもかまいません。私は個人的にそれらについて考えることに多くの努力を払っていませんでした。お役に立てれば。

関連する問題