Dagger 2サブコンポーネントとコンポーネントの依存関係


135

Dagger 1のplus()方法は、以前のアプリケーションでかなり頻繁に使用したものであるため、親グラフバインディングへの完全なアクセス権を持つサブコンポーネントが必要になる状況を理解しています。

どのような状況で、サブコンポーネントの依存関係の代わりにコンポーネントの依存関係を使用することが有益ですか?なぜですか?

回答:


228

コンポーネントの依存関係-2つのコンポーネントを独立させたい場合に使用します。

サブコンポーネント-2つのコンポーネントを結合したままにする場合に使用します。


以下の例を使用して、コンポーネントの依存関係サブコンポーネントを説明します。この例について注意する必要があるポイントは次のとおりです。

  • SomeClassA1依存関係なく作成できます。メソッドModuleASomeClassA1介してのインスタンスを提供しますprovideSomeClassA1()
  • SomeClassB1なしでは作成できませんSomeClassA1ModuleBのインスタンスがメソッドの引数として渡された場合にSomeClassB1のみ、のインスタンスを提供できます。SomeClassA1provideSomeClassB1()
@Module
public class ModuleA {
    @Provides
    public SomeClassA1 provideSomeClassA1() {
        return new SomeClassA1();
    }
}

@Module
public class ModuleB {
    @Provides
    public SomeClassB1 provideSomeClassB1(SomeClassA1 someClassA1) {
        return new SomeClassB1(someClassA1);
    }
}

public class SomeClassA1 {
    public SomeClassA1() {}
}

public class SomeClassB1 {
    private SomeClassA1 someClassA1;

    public SomeClassB1(SomeClassA1 someClassA1) {
        this.someClassA1 = someClassA1;
    }
}

Daggerは、Component / Subcomponent宣言が初期化されるたびに、のインスタンスをSomeClassA1引数としてprovideSomeClassB1()メソッドに渡します。依存関係を満たす方法をダガーに指示する必要があります。これは、コンポーネントの依存関係またはサブコンポーネントを使用して実行できます。ModuleBModuleB

コンポーネントの依存関係

以下のコンポーネント依存関係の例では、次の点に注意してください。

  • ComponentBアノテーションのdependenciesメソッドを介して依存関係を定義する必要があります@Component
  • ComponentA宣言する必要はありませんModuleB。これにより、2つのコンポーネントが独立しています。
public class ComponentDependency {
    @Component(modules = ModuleA.class)
    public interface ComponentA {
        SomeClassA1 someClassA1();
    }

    @Component(modules = ModuleB.class, dependencies = ComponentA.class)
    public interface ComponentB {
        SomeClassB1 someClassB1();
    }

    public static void main(String[] args) {
        ModuleA moduleA = new ModuleA();
        ComponentA componentA = DaggerComponentDependency_ComponentA.builder()
                .moduleA(moduleA)
                .build();

        ModuleB moduleB = new ModuleB();
        ComponentB componentB = DaggerComponentDependency_ComponentB.builder()
                .moduleB(moduleB)
                .componentA(componentA)
                .build();
    }
}

サブコンポーネント

SubComponentの例では、次の点に注意してください。

  • などComponentBへの依存性を定義していないModuleA、それは生きて独立し、することはできません。を提供するコンポーネントに依存しますModuleA。したがって、@Subcomponent注釈があります。
  • ComponentAModuleBインターフェースメソッドを介して宣言されていますcomponentB()。これにより、2つのコンポーネントが結合されます。実際、ComponentBを介してのみ初期化できますComponentA
public class SubComponent {
    @Component(modules = ModuleA.class)
    public interface ComponentA {
        ComponentB componentB(ModuleB moduleB);
    }

    @Subcomponent(modules = ModuleB.class)
    public interface ComponentB {
        SomeClassB1 someClassB1();
    }

    public static void main(String[] args) {
        ModuleA moduleA = new ModuleA();
        ComponentA componentA = DaggerSubComponent_ComponentA.builder()
                .moduleA(moduleA)
                .build();

        ModuleB moduleB = new ModuleB();
        ComponentB componentB = componentA.componentB(moduleB);
    }
}

4
ModuleAをComponentAに追加しないサブコンポーネント設定があります。つまり、componentAビルダーはmoduleBを必要としません。これは、アプリケーションの開始時にComponentAの作成を許可し、mをインスタンス化することを期待していた方法で機能するようです
FriendlyMikhail

2
@MikeN-ComponentAのModuleBを取り除く方法を強調できますか?ComponentAとComponentBに異なるスコープを指定した場合にのみ、ComponentAのModuleBを削除できます。
Praveer Gupta、2015

1
それらは異なるスコープ上にあるので、私のセットアップは正しく動作します。謝罪。
FriendlyMikhail

2
SomeClassB1依存していSomeClassA1ます。依存関係ComponentAを明示的に定義する必要があります。」==>「ComponentB依存関係を明示的に定義する必要がある」という意味ですか?
Tar

1
@Tarが指摘したのと同様に、「SomeClassB1はに依存していSomeClassA1ます。依存関係をComponentA明示的に定義する必要はありません。」「ComponentB依存関係を明示的に定義する必要がない」という意味です。
Sebas LG 2016

45

ドキュメントによると:

Component Dependencyコンポーネントの依存関係を通じてプロビジョニングメソッドとして公開されたバインディングのみにアクセスできます。つまり、parentで宣言されているタイプのみにアクセスできますComponent

SubComponent宣言すると、親からバインディンググラフ全体にアクセスできます。つまり、Modulesで宣言されているすべてのオブジェクトにアクセスできます。

レッツ・発言、あなたの持っているApplicationComponentすべて含むAndroid関連のものを(LocationServiceResourcesSharedPreference、など)。また、APIを処理するDataComponentために、永続化のために物事を管理する場所も必要ですWebService。欠けているのDataComponentは、にApplication ContextあるものだけですApplicationComponent。取得する最も簡単な方法Contextからは、DataComponent上の依存関係になりますApplicationComponentContext宣言されApplicationComponentたものにしかアクセスできないため、明示的に宣言されていることを確認する必要があります。この場合、手動での作業はありません。つまりSubmodules、親Componentで指定してサブモジュールを親モジュールに明示的に追加する必要はありません。

MySubcomponent mySubcomponent = myComponent.plus(new ChildGraphModule("child!")); // No need!

今、あなたは注入したいというケース考えるWebServiceからDataComponentLocationServiceからApplicationComponent、あなたにFragment使ったバインド@Submodule plus上記の機能を。ここで素晴らしいのは、バインドしているコンポーネント(ApplicationComponent)を公​​開する必要がないこと、WebServiceまたはLocationServiceすぐにグラフ全体にアクセスできることです。


2
私が正しく理解していれば、というインターフェースはありません@Submodule。タイプミスですか?
Islam Salah

私はこれが実際の例を使用して違いを紹介する方法が好きです。ただし、これはドキュメントを読むよりも混乱します。classes正確なポイントを説明するために、例としてより少なく、より多くの写真を用意することが役立ちます。
sudocoder

18

以下は、ComponentとSubComponentの理解を深めるためのスクリーンショット付きのコード例です。

成分: ここに画像の説明を入力してください

  1. AppComponentには2つの宣言が含まれています。
  2. AppComponentはAppクラスに初期化されます。
  3. HomeActivityComponentはAppComponentに依存しています。
  4. DaggerHomeActivityComponentの初期化時のHomeActivityでは、AppComponentオブジェクトをコンポジションとして指定しています。

サブコンポーネント:

ここに画像の説明を入力してください

  1. AppComponentには、SubComponentまたはSubComponentsが含まれています。
  2. AppComponentはAppクラスに初期化されます。
  3. SubComponentは、彼のParentComponentを認識していません。これは、モジュールを含めることで独自の依存関係を提供するだけです。
  4. HomeActivityでは、親コンポーネントを使用してSubComponentを注入しています。

そして絵図: ここに画像の説明を入力してください

ソース:リンク


サブコンポーネントがAppComponentを囲んでいる場合、図は意味をなさないでしょうか?
Florian Walther

1

今まで気づかなかったもう1つのことは、

  • @Subcomponent(異なる成分が同じをインスタンス化することができるもののインスタンスは、1つの親コンポーネントを有し@Subcomponent、そのインスタンスの親です)
  • A @Componentは、コンポーネントの依存関係を通じて宣言されたゼロ、1、または多くの「親」コンポーネントを持つことができます

1
おそらく2番目のケースでは、「@ Component」が...親を持っているかもしれないと言うのは正しくありません。むしろ '@Component'には親がありませんが、コンポーネントの依存関係を介して(単にそれを使用するだけで)依存しているものもあります。
demaksee 2018

@demakseeわかりません。コンポーネントの階層をマッピングすると、DAGに到達するようです。これは、グラフのコンテキストでこの関係を親子として参照する標準的な方法だと思います。ダガーの内部の仕組みについて話しているとしたら、それは正しい言葉ではないかもしれません。
arekolek
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.