8

私はDaggerを使用して Android アプリケーションに依存関係を注入していますが、クリーンな方法で解決する方法が完全にはわからない問題に遭遇しました。

私が達成しようとしているのは、ヘルパーをインスタンス化してアクティビティ内に注入し、これらのヘルパーにも注入されたメンバーを含めることです。

機能するもの

私のヘルパーが注入されているアクティビティ:

public class MyActivity extends Activity {
    @Inject SampleHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ((MyApplication) getApplication()).inject(this);

        Log.i("debug", "helper = " + helper);
        Log.i("debug", "helper context = " + helper.context);
    }
}

オブジェクト グラフを作成するアプリケーション:

public class MyApplication extends Application {
    private ObjectGraph graph;

    @Override
    public void onCreate() {
        super.onCreate();

        graph = ObjectGraph.create(getModules());
    }

    private Object[] getModules() {
        return new Object[] { new MyModule(this) };
    }

    public void inject(Object target) {
        graph.inject(target);
    }
}

インジェクションは、SampleHelper クラスを直接インスタンス化すると完全に機能し、次に、インジェクトされたアプリケーション コンテキストを受け取ります。

@Singleton
public class SampleHelper {

    @Inject public Context context;

    @Inject
    public SampleHelper() {}
}

次のモジュールを使用します。

@Module(
    injects = { MyActivity.class },
    complete = false,
    library = true
)
public class MyModule {
    private final MyApplication application;

    public MyModule(MyApplication application) {
      this.application = application;
    }

    @Provides @Singleton Context provideApplicationContext() {
        return application;
    }
}

うまくいかないこと

ただし、ヘルパー インターフェイスをその実装から分離すると、次のようになります。

public interface SampleHelper {
}

@Singleton
public class SampleHelperImpl implements SampleHelper {

    @Inject public Context context;

    @Inject
    public SampleHelperImpl() {}
}

そして、これを短剣モジュールに追加します:

public class MyModule {
    ...

    // added this method
    @Provides @Singleton public SampleHelper provideSampleHelper() {
        return new SampleHelperImpl();
    }

    ...
}

予想どおり、SampleHelperImpl にコンテキストが挿入されません。さて、これは、インジェクションによって開始されたコンストラクター呼び出しではなく、直接コンストラクター呼び出しによって SampleHelperImpl がインスタンス化されたためだと思います。 MyModule#provideApplicationContext() が呼び出されることさえないためです。おそらく、以前の DI の経験には Spring のみが含まれていたためです)。

「クリーンダガー」の方法で、注入されたヘルパー実装にコンテキストを注入する方法についてのアイデアはありますか?

どうもありがとう!

4

4 に答える 4

18

これはかなり古い質問ですが、あなたが望むのはこれだと思います:

@Provides @Singleton public SampleHelper provideSampleHelper(SampleHelperImpl impl) {
    return impl;
}

このようにして、短剣はあなたを作成しSampleHelperImpl、それを注入します。

于 2013-08-27T00:27:11.780 に答える
1

(ダガー v1.0.1 に適用)

アダプター注入を使用していることを確認してください。反射注入を使用すると、ダガーは明らかに@Providesオブジェクトに推移的な注入を行いません。これはバグだと思います。

于 2013-07-23T16:14:28.710 に答える
1

誰かが興味を持っている場合に備えて、 @Provides メソッドを短剣モジュールに実装すると、次のように短剣で処理されるオブジェクトのインスタンスを取得できます。

@Provides @Singleton public SampleHelper provideSampleHelper(Context context) {
    SampleHelper helper = new SampleHelperImpl();
    helper.setContext(context);
    return helper;
}

これは機能しますが、ヘルパー セッターを明示的に呼び出す必要があるため (通常は、インジェクションで取り除きたいもの)、まだ少し不器用だと感じています。

(誰かがより良い解決策を見つけた場合に備えて、私は少し待ちます)

于 2013-07-16T08:14:27.457 に答える