3

の Dagger1 仕様を通じてモジュールがすべて相互に共有されていることを考慮すると、メソッドによって提供される要素をコンストラクター パラメーターを通じてcomplete=false, library=true受け取ることができます。@Provides

public class GetUserForUsernameTaskImpl
        implements GetUserForUsernameTask {
    public static final String TAG = GetUserForUsernameTaskImpl.class.getSimpleName();

    private Realm realm;
    private UserRepository userRepository;

    public GetUserForUsernameTaskImpl(Realm realm, UserRepository userRepository) {
        this.realm = realm;
        this.userRepository = userRepository;
    }

    @Override
    public RealmResults<UserRLM> getUsers() {
        try {
            RealmResults<UserRLM> users = userRepository.findAll(realm);
    ...
}

@Module(includes = {RepositoryModule.class, RealmModule.class})
public class DatabaseTaskModule {
    @Provides
    public GetUsersDatabaseTask getUsersDatabaseTask(Realm realm, UserRepository userRepository) {
        return new GetUsersDatabaseTaskImpl(realm, userRepository);
    }
}

Presenterただし、コンポーネント グラフを保持する依存関係 (またはインスタンス) を1 つだけ指定CustomApplicationし、そのコンポーネント グラフを使用して実装クラスを注入することもできます。

public class GetUserForUsernameTaskImpl
        implements GetUserForUsernameTask {
    public static final String TAG = GetUserForUsernameTaskImpl.class.getSimpleName();

    @Inject
    public Realm realm;
    @Inject
    public UserRepository userRepository;

    protected Presenter presenter;
    private boolean isInjected = false;

    public GetUserForUsernameTaskImpl(Presenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public RealmResults<UserRLM> getUsers() {
        if(!isInjected) {
            presenter.getPresenterComponent().inject(this);
            isInjected = true;
        }
        try {
            RealmResults<UserRLM> users = userRepository.findAll(realm);
            ...
    }
}

@Module(includes = {PresenterModule.class})
public class DatabaseTaskModule {
    @Provides
    public GetUsersDatabaseTask getUsersDatabaseTask(Presenter presenter) {
        return new GetUsersDatabaseTaskImpl(presenter);
    }
}

そうすれば、プレゼンターのオブジェクト グラフに依存するだけで済み、コンストラクターのパラメーターをいじる必要がなくなります。

どちらがより良いアプローチですか?

編集:あまりよくリファクタリングされていないプロジェクトで私が持っているより明確で具体的な例は次のとおりです:

@Module(includes = {ContextModule.class})
public class ClientAuthModule {
    @Provides
    public ClientAuthAuthenticator clientAuthAuthenticator(CustomApplication customApplication) {
        return new ClientAuthAuthenticator(customApplication);
    }
}

それで

public class CustomApplication
        extends Application {
    public static class InjectorInitializedEvent {
    }

    public static class InjectorInitializedEventProducer {
        @Produce
        public InjectorInitializedEvent produceEvent() {
            return new InjectorInitializedEvent();
        }
    }

    private ApplicationComponent applicationComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        applicationComponent = Injector.INSTANCE.initializeApplicationComponent();
        SingletonBus.INSTANCE.getBus().post(new InjectorInitializedEvent());
        SingletonBus.INSTANCE.getBus().register(new InjectorInitializedEventProducer()); //OTTO bus, event producer
    }

    public ApplicationComponent getApplicationComponent() {
        return this.applicationComponent;
    }
}

それで

public class ClientAuthAuthenticator {
    private CustomApplication customApplication;

    @Inject
    public PEMConverter pemConverter;
    @Inject
    public KeyPairCreator keyPairCreator;
    @Inject
    public PKCS10CsrCreator pkcs10CsrCreator;
    @Inject
    public KeyPairReader keyPairReader;
    //...

    public ClientAuthAuthenticator(CustomApplication customApplication) {
        this.customApplication = customApplication;
        SingletonBus.INSTANCE.getBus().register(this);
    }

    @Subscribe
    public void onInjectorInitializedEvent(CustomApplication.InjectorInitializedEvent e) {
        customApplication.getApplicationComponent().inject(this);
        SingletonBus.INSTANCE.getBus().unregister(this);
    }

    ...

質問:この方法では、すべての依存関係は、コンストラクターではなく、インジェクターの準備が整ったときにアプリケーションのコンポーネントから提供されます。しかし、これは良いアプローチですか?長期的には注意点はありますか?

EDIT2:ここにインジェクターを持っていましたが、かなり悪かったです。

私が他のプロジェクトで持っているものは、よりよく構築されていました。

4

2 に答える 2

1

コンストラクター注入メソッドを使用すると、標準の JSR-330 アノテーションでクラスにアノテーションを付けるだけなので、次のようになります。

  • コードは、使用している具体的な依存性注入ライブラリから分離されています。たとえば古いバージョンのダガーに戻す必要がある場合は、コア クラスではなく、モジュールとコンポーネントの定義のみを変更する必要があります。

  • クラスは、生成方法の詳細を認識する必要はありません。明日は、スコープに応じてさまざまなコンポーネントを使用するか、プレゼンター クラスからコンポーネントを取り出したいと思うかもしれません。このため、コアクラスを変更しないでください。

  • モジュールのテストが容易になります。コード生成を実行したり、アプリケーションを介してコンポーネント インスタンスを置き換えたりする必要はありません。モックまたはテスト モジュールをコンストラクターに直接挿入するだけで完了です。

フィールドとメソッドの注入は、モジュールのライフサイクルが制御できない場合にのみ使用してください。これは、Android 環境のアクティビティまたはフラグメントの場合です。そのユースケース以外では、これらのメソッドは問題の原因にすぎません。

于 2015-06-28T20:28:00.147 に答える