web-dev-qa-db-ja.com

Dagger2を使用しながら循環依存関係を解決するにはどうすればよいですか?

私は2つのクラス、Foo<T>Barは互いに依存しているだけでなく、他のさまざまなクラスにも依存しています。依存関係の挿入にDagger-2を使用していますが、循環依存関係を単純に追加すると、Daggerは実行時にスタックオーバーフローをヒットします。これを修正するためにクラスをリファクタリングしながら、Daggerを使用して他のすべての依存関係を挿入し、重複と既存の呼び出しへの変更を最小限に抑える良い方法は何ですか?

簡単な方法は、Lazy<T>片側。

Lazy<Foo> foo;

@Inject
Bar(Lazy<Foo> foo) {
    this.foo = foo;
}

// use foo.get(); when needed
35
EpicPandaForce

過度の思考と同僚との会話の後、私たちは結局次のことをしました:

class Foo<T> extends FooWithoutDep<T> {
    @Inject Foo(Bar bar, OtherDep1 dep1, OtherDep2 dep2) {
        super(dep1, dep2);
        setBarDep(bar);
    }
}

class FooWithoutDep<T> {
    //Field declarations elided
    @Inject FooWithoutDep(OtherDep1 dep1, OtherDep2 dep2) {
        //Normal constructor stuff
    }
    void setBarDep(Bar bar) { this.bar = bar; }

    //The rest of the actual logic
}

class Bar {
    //Field declarations elided
    @Inject Bar(FooWithoutDep<Thing> foo, OtherDep3 dep3) {
        this.foo = foo;
        this.foo.setBarDep(this);
        this.dep3 = dep3;
    }

    //Code that uses Foo and the other dependencies
}

これを説明する-Fooの実際のロジックを親クラス(FooWithoutDep)に移動しました。これは、循環依存関係をコンストラクターパラメーターではなく設定可能なフィールドとして受け取りました。次に、元のクラスには、循環依存関係を取得してセッターを呼び出すコンストラクターが含まれています。もう1つのクラスであるBarは、親(FooWithoutDep)に依存し、セッターを明示的に呼び出し、それ自体を渡しました(this)。これにより、Daggerを使用してすべての依存関係を挿入しながら、クラスへの既存のすべての参照を同じままにすることができます。

これは、ここに書く価値があるほど十分に混乱しているように見えました。

これは、親クラスなしで解決した方法です。

クラス1:エンジン。 (コンポーネントインターフェース内)@Provides public Engine myEngine(Context context){return new Engine(context); }

クラス2:パーツ。エンジンにもパーツインスタンスが必要ですが、作成が遅れます。

@Inject
public Parts(Context context, Engine engine) {
    this.context = context;
    this.engine= engine;
    engine.setParts(this);
}

循環依存は達成できますが、一方のクラスを最初に開始してから、もう一方のクラスを開始する必要があります。

ここでも、可能であれば、循環DIを回避するためにコードをリファクタリングします。