2017-03-29 11 views
2

以下はすべて、ダガー2.10とdagger.androidパッケージで使用されています。複数の@同じリターンクラスで異なるキーのバインド

私はクラスを複数のアクティビティで使用したいと思います。

public class DemoSharedClass { 
    Activity activity; 

    @Inject public DemoSharedClass(Activity activity) { 
    this.activity = activity; 
    } 
} 

その後、最新のダガーAPIを使用して、私のクラスは

public class DemoActivity extends DaggerActivity { 
    @Inject DemoSharedClass demoSharedClass; 

    // ... 
} 

public class Demo2Activity extends DaggerActivity { 
    @Inject DemoSharedClass demoSharedClass; 

    // ... 
} 

のように定義されている各アクティビティは、そのモジュールおよびサブコンポーネントとして定義します(Demo2Activityのために同じことをexactement)

@Module(subcomponents = DemoActivitySubcomponent.class) 
public abstract class DemoActivityModule { 
    @Binds 
    @IntoMap 
    @ActivityKey(DemoActivity.class) 
    abstract AndroidInjector.Factory<? extends Activity> 
    bindDemoActivityInjectorFactory(DemoActivitySubcomponent.Builder builder); 

    // This is set so SharedClass can be injected using its constructor 
    // There is the same in Demo2ActivityModule 
    @Binds abstract Activity bindActivity(DemoActivity demoActivity); 
} 

@Subcomponent 
public interface DemoActivitySubcomponent extends AndroidInjector<DemoActivity> { 
    @Subcomponent.Builder 
    abstract class Builder extends AndroidInjector.Builder<DemoActivity> {} 
} 

を持っています最後に、appコンポーネントは、

@Component(modules = { 
    ApplicationModule.class, 
    AndroidInjectionModule.class, 
    DemoActivityModule.class, 
    Demo2ActivityModule.class, 
}) 
interface DemoApplicationComponent { 
    DemoApplication injectApplication(DemoApplication application); 
} 
と定義されています私はプロジェクトをビルドするとき

は今、私はこのエラーを取得する:

Error:(11, 11) error: [dagger.android.AndroidInjector.inject(T)] android.app.Activity is bound multiple times: 
@Binds android.app.Activity dagger.demo.DemoActivityModule.bindActivity(dagger.demo.DemoActivity) 
@Binds android.app.Activity dagger.demo.Demo2ActivityModule.bindActivity(dagger.demo.Demo2Activity) 

私はエラーを取得し、私は彼らが同じスコープ、アプリケーションのコンポーネントであるため、これがあると思います。

両方のDemoSubcomponentsに共通のモジュールを作成すると、次のようなものになりますが、同様のエラーが発生すると考えました。

@Module 
public abstract class SharedClassModule { 
    @Binds abstract Activity bindContext(DemoActivity demoActivity); 
    @Binds abstract Activity bindContext(Demo2Activity demo2Activity); 
} 

質問:どうすればいいですか?

+0

あなたはアプリケーションクラス内にDemoApplicationComponentを構築していますか? – Avi

答えて

5

あなたは、各サブコンポーネント上の別々の結合必要があります:ダガーはDispatchingAndroidInjectorからAndroidInjector.Builder.create()に呼び出す、ためAndroidInjector.Builder@BindsInstance Builder seedInstance(DemoActivity)

@Module interface DemoActivitySubcomponentModule { 
    @Binds abstract Activity bindContext(DemoActivity demoActivity); 
    // ...other bindings unique to DemoActivity and not DemoActivity2 
} 

@Subcomponent(modules={DemoActivitySubcomponentModule.class}) 
public interface DemoActivitySubcomponent extends 
    AndroidInjector<DemoActivity> { 
    @Subcomponent.Builder 
    abstract class Builder extends AndroidInjector.Builder<DemoActivity> {} 
} 

を、ダガーは少なくともDemoActivityインスタンスを提供する方法を知っているん。ただし、DemoActivityとActivity(またはContext)の間にビルトインバインディングはないため、バインディングはコンポーネントではなくサブコンポーネントで行う必要があります。そのバインディングを持つモジュールを適切な@Subcomponentに置くことによって、それぞれのサブコンポーネント内でActivityバインディングがDaggerが知っている正しいタイプになるようにすることができます。

DemoActivityModuleでのバインディング@Binds @IntoMap @ActivityKey(...)はまだApplicationComponentに移動する必要があるため、ApplicationComponentは、注入するアクティビティのクラスからどのサブコンポーネントを作成するかを決定できます。具体的には、新しいDemoActivitySubcomponentModuleをDemoActivitySubcomponentに移動し、DemoActivity2Subcomponentがそれを見ることができない場所でActivity-to-DemoActivityを行うようにします。

副次的な問題として、表示されている問題は、同じコンポーネントで発生するActivityへの2つのバインディング間の競合です。 (@ActivityScopeのようなスコープアノテーションを各サブコンポーネントに追加することもできますが)ここではスコープアノテーションはありません。 seedInstanceは、現在適用されていない各サブコンポーネント内にのみ適用されます。これは、祖先コンポーネントとサブコンポーネント固有モジュールのバインディングと組み合わされます。

+0

ありがとうございます。私は不思議ですが、ドキュメンテーションでなぜサブコンポーネントの対応モジュールがステップ3のアプリケーションコンポーネント、https://google.githubに追加されているのですか。io/dagger/android.html#injecting-activity-objectsあなたの答えに示されているように、対応するサブコンポーネントのモジュールリストに追加してはいけませんか? – oldergod

+0

いいえ、2つの別々のコンポーネントがここにあり、1つのモジュールがそれぞれ入ります。 _Application_コンポーネント( '@ Singleton')は、アプリケーションコンポーネントが正しいサブコンポーネントを作成することを可能にする' @ IntoMap'マルチバインディングを持つ必要があります。一般的なアクティビティやコンテキスト(YourActivityからのキャストのみ)が必要ない場合は、他のモジュールを無視して逃げることができます。しかし、アクティビティやコンテキストが必要な場合は、YourActivityまたはDemoActivityがバインドされているコンポーネントに移動する必要があるため、サブコンポーネント上の別のモジュールに移動する必要があります。 –

+0

ありがとうございます。ドキュメントでは、サブコンポーネントの対応するモジュールがアプリケーションコンポーネント@Component(modules = {...、YourActivityModule.class})に入り、YourApplicationComponent {} 'をインタフェースします。なぜですか?サブコンポーネントに直接設定されていないのはなぜですか? @Subcomponent(modules = ...) 公開インタフェースYourActivitySubcomponent'。それは私の混乱の一部であり、私はここでこの質問をしています。 – oldergod

関連する問題