15

Dagger 2 を使用して、1 つのスコープ内の複数の場所にシングルトン オブジェクトを挿入しようとしています。ただし、私のソリューションでは代わりに毎回新しいインスタンスが作成されるようです。

このテスト プロジェクトには、DaggerModule を初期化する MainActivity があります。DaggerModule はオブジェクト Box と Cat を提供し、Box はパラメーターとして Cat を取ります。また、MainActivity で Cat を取り込みます。最後に、注入された両方の Cat 変数の参照 (それぞれ Box と MainActivity で) を確認しますが、それらは同じインスタンスではありません。

代わりに MainActivity で provideCat() を 2 回呼び出すと、同じインスタンスが提供されます。

主な活動:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerModule daggerModule = new DaggerModule();
        DaggerComponent daggerComponent = Dagger_DaggerComponent.builder()
                .daggerModule(daggerModule).build();

        // Same Cat instance returned.
        Cat cat1 = daggerComponent.provideCat();
        Cat cat2 = daggerComponent.provideCat();
        Log.d("=== cat1: ", cat1.toString());
        Log.d("=== cat2: ", cat2.toString());

        // Different Cat instance returned. Why?
        Box box = daggerComponent.provideBox();
        Log.d("=== box cat: ", box.getCat().toString());
    }
}

@Module
public class DaggerModule {

    @Provides
    @Singleton
    public Cat provideCat() {
        return new Cat();
    }

    @Provides
    @Singleton
    public Box provideBox() {
        return new Box(provideCat());
    }

}

@Singleton
@Component(modules = { DaggerModule.class })
public interface DaggerComponent {

    Cat provideCat();

    Box provideBox();

}

public class Cat {

    @Inject
    public Cat() {
    }

}

public class Box {

    private Cat mCat;

    @Inject
    public Box(Cat cat) {
        mCat = cat;
    }

    public Cat getCat() {
        return mCat;
    }

}

前もって感謝します!

編集: provideBox 内から直接 provideCat を呼び出す代わりに、provideBox が Cat 引数を取り、それを使用して Box を作成する場合に機能します。

    // Doesn't work, new Cat instance created.
    @Provides
    @Singleton
    public Box provideBox() {
        return new Box(provideCat());
    }

    // Works, same singleton injected.
    @Provides
    @Singleton
    public Box provideBox(Cat cat) {
        return new Box(cat);
    }

MainActivity での provideCat の呼び出しと、DaggerModule の provideBox 内からの呼び出しの違いは何ですか? Dagger コンパイラが外部クラスと同じように DaggerModule を処理せず、そこで provideCat を呼び出すと注釈が適用されない可能性がありますか?

4

1 に答える 1

8

provideBox 内から provideCat を呼び出そうとした理由は、Component インターフェイスに関する私の誤解でした。Component インターフェイスは実際には Module によって実装されていないため、Module のメソッドの引数を Component の対応するメソッドで宣言する必要がないと誤解していました。その場合は、MainActivity の provideBox メソッド呼び出しで Cat インスタンスを作成する必要がありましたが、これは避けたかったのです (したがって、モジュールの provideBox メソッドで provideCat を直接呼び出します)。実際、Component メソッドで引数を宣言すると、Dagger コンパイラがコンパイルできなくなりました。

しかし、コンポーネントのメソッドは引数をとらないため、解決策は、(モジュール自体から対応する提供メソッドを呼び出すのではなく) 必要に応じてインスタンスをモジュールのメソッドに引数として挿入し、コンポーネントのパラメーターなしのメソッドを呼び出すだけで済みました。次のように MainActivity から:

主な活動:

Cat cat = daggerComponent.provideCat();
Box box = daggerComponent.provideBox();

成分:

Cat provideCat();
Box provideBox(); <- no arguments

モジュール:

@Module
public class DaggerModule {

    @Provides
    @Singleton
    public Cat provideCat() {
        return new Cat();
    }

    @Provides
    @Singleton
    public Box provideBox(Cat cat) { <- arguments
        return new Box(cat);
    }

}

MainActivity と Box の Cat シングルトン インスタンスは同じになり、MainActivity からそれらを宣言する必要はありませんでしたが、Dagger がすべて処理しました。成功!ただし、提供メソッドが外部クラスから呼び出された場合とモジュール自体から呼び出された場合の動作が異なる理由はまだわかりません。

于 2015-04-03T22:16:02.883 に答える