web-dev-qa-db-ja.com

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

Dagger 1のplus()メソッドは、以前のアプリケーションで非常に頻繁に使用したものであるため、親グラフバインディングにフルアクセスできるサブコンポーネントが必要な場合があることを理解しています。

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

117

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

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


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

  • SomeClassA1は、依存関係なしで作成できます。 ModuleAは、provideSomeClassA1()メソッドを介してSomeClassA1のインスタンスとインスタンスを提供します。
  • SomeClassB1は、SomeClassA1なしでは作成できません。 ModuleBは、SomeClassB1のインスタンスがprovideSomeClassB1()メソッドの引数として渡される場合にのみ、SomeClassA1のインスタンスを提供できます。
@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は、ModuleBを宣言するコンポーネント/サブコンポーネントが初期化されるたびに、ModuleBprovideSomeClassB1()メソッドへの引数としてSomeClassA1のインスタンスを渡します。依存関係を満たす方法をDaggerに指示する必要があります。これは、コンポーネント依存関係またはサブコンポーネントを使用して実行できます。

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

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

  • ComponentBは、@Componentアノテーションのdependenciesメソッドを介して依存関係を定義する必要があります。
  • ComponentAModuleBを宣言する必要はありません。これにより、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の例では、次の点に注意してください。

  • ComponentBModuleAへの依存関係を定義していないため、独立して存続することはできません。 ModuleAを提供するコンポーネントに依存します。したがって、@Subcomponent注釈があります。
  • ComponentAは、インターフェイスメソッドcomponentB()を介してModuleBを宣言しました。これにより、2つのコンポーネントが結合されます。実際、ComponentBComponentAを介してのみ初期化できます。
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);
    }
}
205
Praveer Gupta

ドキュメント によると:

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

SubComponentは、宣言時に親からentireバインディンググラフへのアクセスを提供します。つまり、Modulesで宣言されたすべてのオブジェクトにアクセスできます。

たとえば、ApplicationComponentに関連するすべてのもの(AndroidLocationServiceResourcesなど)を含むSharedPreferenceがあるとします。また、DataComponentと共に永続化のために物事を管理するWebServiceを持ち、APIを処理します。 DataComponentに欠けているのは、ApplicationComponentにあるApplication Contextだけです。 ContextからDataComponentを取得する最も簡単な方法は、ApplicationComponentに依存することです。 Contextで明示的に宣言されているApplicationComponentがあることを確認する必要があります。これは、宣言されたものにしかアクセスできないためです。この場合、手作業はありません。つまり、親SubmodulesComponentを指定し、サブモジュールを次のように親モジュールに明示的に追加する必要はありません。

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

ここで、上記の@SubmoduleWebService機能を使用してバインドするDataComponentからLocationServiceおよびApplicationComponentからFragmentplusに挿入する場合を考えてみましょう。ここでクールなのは、(ApplicationComponent)にバインドしているコンポーネントはnotWebServiceまたはLocationServiceを公開する必要があることです。これは、グラフ全体にアクセスできるためです。直ちに。

43
Eugene

コンポーネントとサブコンポーネントをさらに理解するためのスクリーンショット付きのコード例を次に示します。

コンポーネント:enter image description here

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

サブコンポーネント:

enter image description here

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

そして絵図:enter image description here

ソース: link

11
0xAliHn

今まで気づかなかったもう1つのことは、次のとおりです。

  • @Subcomponentインスタンスには、親コンポーネントが1つだけあります(ただし、異なるコンポーネントが同じ@Subcomponentをインスタンス化し、そのインスタンスの親になることができます)
  • @Componentには、 コンポーネントの依存関係 で宣言された0、1、または多くの親コンポーネントがあります
2
arekolek