【问题标题】:Dagger2: Injecting implementation classes provided by modules with component itselfDagger2:用组件本身注入模块提供的实现类
【发布时间】:2015-05-31 08:18:01
【问题描述】:

考虑到模块都是通过complete=false, library=true的Dagger1规范相互共享的,你可以通过构造函数参数接收@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);
    }
}

但是,您也可以仅指定一个包含组件图的依赖项(PresenterCustomApplication 实例),并使用该组件图注入您的实现类。

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:我这里有注射器,但很糟糕。

我有一个in my other project was better constructed

【问题讨论】:

  • 你能添加你的 Injector-class 吗?

标签: java android dagger-2


【解决方案1】:

使用构造函数注入方法你只是用标准的 JSR-330 注释来注释你的类,所以:

  • 代码与您正在使用的具体依赖注入库分离。如果您需要返回到旧版本的 dagger,则只需更改您的模块和组件定义,而不是您的核心类。

  • 您的类不需要知道它们是如何生成的细节。明天您可能会根据范围拥有不同的组件,或者您可能希望将您的组件从演示者类中取出。您的核心课程不应因此而改变。

  • 它使您的模块测试更加容易。无需通过您的应用程序运行代码生成或替换组件实例。只需在构造函数中直接注入模拟或测试模块即可。

字段和方法注入仅应在模块的生命周期超出您控制范围的情况下使用。这将是 Android 环境中的活动或片段的情况。在该用例之外,这些方法只是问题的根源。

【讨论】:

    【解决方案2】:

    如果你的依赖是通过组件/模块提供的,那么当依赖被创建时,组件将一直存在。所以你可以在它的构造函数中调用字段注入。再简单不过了。

    【讨论】:

      猜你喜欢
      • 2020-12-26
      • 2015-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      相关资源
      最近更新 更多