7

http://konmik.github.io/snorkeling-with-dagger-2.htmlに基づいて、単純な Dagger 2 テストセットアップを用意しました。すべての設定を出力する PreferenceLogger を挿入します。注入されたクラスでは、さらにクラスを @Inject できます。

public class MainActivity extends Activity {
    @Inject PreferencesLogger logger;
    @Inject MainPresenter presenter;

    @Override protected void onCreate(Bundle savedInstanceState) {
    MyApplication.getComponent().inject(this);
    presenter.doStuff();
        logger.log(this);
    }
}


public class PreferencesLogger {

    @Inject OkHttpClient client;
    @Inject public PreferencesLogger() {}

    public void log(Contect context) {
    // this.client is available
    }
}

これを実行すると、ロガーが設定され、PreferencesLogger.log 内で OkHttpClient が正しく設定されます。したがって、この例は期待どおりに機能します。今、私はMVP構造を整えようとしています。実装のある MainPresenter インターフェイスがあります。MainActivity で次を設定します。

@Inject MainPresenter presenter;

そのため、この MainPresenter を別の (デバッグまたはテスト) 実装に切り替えることができました。もちろん、使用する実装を指定するモジュールが必要です。

public interface MainPresenter {
    void doStuff();
}

public class MainPresenterImpl implements MainPresenter {

    @Inject OkHttpClient client;

    public MainPresenterImpl() {}

    @Override public void doStuff() {
    // this.client is not available    
    }
}


@Module public class MainActivityModule {
    @Provides MainPresenter provideMainPresenter() {
        return new MainPresenterImpl();
    }
}

OkHttpClient が注入されなくなったという問題が発生しました。もちろん、パラメーター OkHttpClient を受け入れるようにモジュールを変更することもできますが、これが推奨される方法ではないと思います。MainPresenterImpl が正しく注入されない理由はありますか?

4

2 に答える 2

5

MainPresenterImplコンストラクター注入を使用して注入できる可能性があります。

/* unscoped */
public class MainPresenterImpl implements MainPresenter {

    @Inject 
    OkHttpClient client;

    @Inject
    public MainPresenterImpl() {
    }

    @Override public void doStuff() {
       // this.client is now available! :)
    }
}


@Module 
public class AppModule {
    private MyApplication application;

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

    @Provides
    /* unscoped */ 
    public MyApplication application() {
        return application;
    }
}

@Module 
public abstract class MainActivityModule {
    @Binds public abstract MainPresenter mainPresenter(MainPresenterImpl mainPresenterImpl);
}
于 2015-05-31T09:02:47.637 に答える
4

コンストラクター注入とは異なり、メソッド@Injectで構築された依存関係の注釈付きフィールドは@Provides自動的に注入できません。フィールドを注入できるようにするには、そのモジュールでフィールドの型を提供するコンポーネントが必要であり、プロバイダー メソッド自体では、そのような実装は利用できません。

presenterフィールドが に挿入されるとMainActivity、プロバイダー メソッドが呼び出されpresenter、その戻り値が設定されるだけです。あなたの例では、引数なしのコンストラクターは初期化を行わず、プロバイダー メソッドも初期化を行わないため、初期化は行われません。

ただし、プロバイダー メソッドは、パラメーターを介して、モジュールで提供される他の型のインスタンスにアクセスできます。プロバイダーメソッドでパラメーターを使用することは、提供されたタイプの依存関係を「注入」するための推奨される (唯一の) 方法であると思います。これは、モジュール内の依存関係として明示的に示し、コンパイル時に Dagger がエラーをスローできるようにするためです。 -満足できない場合は時間。

現在エラーをスローしていない理由は、注入のターゲットがどこかでなくても、依存関係が満たされるMainPresenterImpl 可能性があるためです。ダガーは、インターフェース型のメンバー注入メソッドを作成できません。インターフェースとして、注入可能なフィールドを持つことができず、実装型のフィールドを自動的に注入しないためです。これは、プロバイダー メソッドを提供するだけだからです。戻り値。OkHttpClientMainPresenterImplMainPresenter

于 2015-05-06T06:04:39.753 に答える