如何告诉Dagger 2基于X实例化哪个实现?

乔列斯基:

在模块内部,如果我需要基于模块构造时已知的变量提供接口的不同实现,则可以将逻辑放入该接口类型的@Provides方法中。像这样:

@Module
public class FooModule {

    private final State state;

    public FooModule(State state) {
        this.state = state;
    }

    @Provides
    FooInterface provideFooImplementation() {
        switch(state) {
            case STATE_1:
                return new FooImpl1();
            case STATE_2:
                return new FooImpl2();
            ...
            case STATE_10:
                return new FooImpl10();
        }
    }
}

但是,这些实现可以由Dagger创建。我宁愿说“嘿,基于XI希望您为我实例化此类”

我考虑了几种选择。

  1. 更改提供方法以采用所有可能的实现:

    @Provides
    FooInterface provideFooImplementation(FooImpl1 impl1, FooImpl2 imp2, ..., FooImpl10 impl10) {
        switch(state) {
            case STATE_1:
                return impl1;
            case STATE_2:
                return impl2;
            ...
            case STATE_10:
                return impl10;
        }
    }
    

这允许Dagger实例化它们并满足它们的所有依赖关系,但是如果每个实现都相对较大或创建成本很高,则不是一个好主意。

  1. 更改Provides方法以获取不同实现的所有依赖项的集合。

    @Provides
    FooInterface provideFooImplementation(Context context, Repo repo, HttpClient httpClient, ...) {
        switch(state) {
            case STATE_1:
                return new FooImpl1(context);
            case STATE_2:
                return new FooImpl2(repo, httpClient);
            ...
            case STATE_10:
                return new FooImpl10(context, repo);
        }
    }
    

这比选项1稍好一点,因为Dagger不必实例化每个单个实现,但是,即使可能并非在所有情况下都使用它们,它仍然需要实例化所有依赖关系。我也要自己创建对象,即使它们可以由Dagger创建。

  1. 每个实现创建一个模块,并实例化适当的模块。所以像:

    @Module
    public FooImpl1Module {
    
        @Provides
        FooInterface provideFooImplementation(Context context) {
            return new FooImpl1(context);
        }
    }
    

很好,但是现在我在定义依赖于模块的组件时遇到了问题。

解决此问题的最佳方法是什么?

一种建议是尝试使用包含在Lazy中的参数的选项1。然后,我最终只对其中一个调用.get()。我会尽量尝试并发布结果

杰夫·鲍曼(Jeff Bowman):

而不是使用Lazy<T>选项1 Provider<T>Lazy<T>只是一个Provider<T>在本地存储的(具有必要的双重检查锁定),但是因为您知道只将一个提供者调用一次,所以您可以注入该提供者,而跳过同步开销。

@Provides
FooInterface provideFooImplementation(
        Provider<FooImpl1> impl1,
        Provider<FooImpl2> impl2,
        ...,
        Provider<FooImpl10> impl10) {
    switch(state) {
        case STATE_1:
            return impl1.get();
        case STATE_2:
            return impl2.get();
        ...
        case STATE_10:
            return impl10.get();
    }
}

选项2可以使用,但是您将有效地跳过Dagger可以轻松为您完成的依赖关系接线,并且选项3不能按所述方式工作,因为@Component注释需要模块列表作为您的编译时常量Dagger代码生成可以正常工作。

(如果将绑定绑定到一种形式或另一种形式的常数或零依赖类,则选项3的变体可以工作,因为这样您可以将Module的任意子类传递到Component Builder中。但是,Dagger只能分析如果您的@Provides方法实现采用的参数与您使用的参数不同,那么您将遇到麻烦,因此,这switch是我能想到的最好,最清晰的替代方法。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章