首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Dagger-2惰性注入接口?

如何使用Dagger-2惰性注入接口?
EN

Stack Overflow用户
提问于 2019-04-08 16:17:01
回答 1查看 2.1K关注 0票数 0

我遇到了一个例子,达格-2不让我偷懒注射。它似乎仍然需要我在编译时提供对象。为什么会这样呢?

堆叠痕迹:

代码语言:javascript
复制
[Dagger/MissingBinding] @javax.inject.Named("htfModel") de.wimj.core.Applications.IModel cannot be provided without an @Provides-annotated method.
[ERROR]       @javax.inject.Named("htfModel") de.wimj.core.Applications.IModel is injected at
[ERROR]           de.wimj.ui.Mt5Painter.<init>(…, htfTradeModel, …)
[ERROR]       dagger.Lazy<de.wimj.ui.Mt5Painter> is injected at
[ERROR]           de.wimj.core.Applications.ModelMqlBased.<init>(…, mt5Painter, …)
[ERROR]       dagger.Lazy<de.wimj.core.Applications.ModelMqlBased> is injected at
[ERROR]           de.wimj.di.components.trademodel.ModelModule.iModel(modelMqlBased, …)
[ERROR]       de.wimj.core.Applications.IModel is provided at
[ERROR]           de.wimj.di.components.trademodel.ModelComponent.createModel()

堆栈跟踪的代码:

代码语言:javascript
复制
//Got it, Dagger-2 wants me to provide a IModel here
@ModelScope
@Component(modules = { ModelModule.class }, dependencies = { ClientComponent.class })
public interface ModelComponent {

    IModel createModel();

    @Component.Builder
    interface Builder {
        ModelComponent build();
        Builder clientComponent(ClientComponent clientComponent); //MT5Trader comes from this component
    }

}


//At this point I will provide the IModel. I do NOT get, why Dagger-2 forces
//me to provide a "ModelMqlBased" though. I obviously lazy-inject it. 
//I used this pattern in other cases as well (providing an interface and 
//lazy-injecting the possible instantiations as params)
@Module
public class ModelModule {

    @Provides
    @ModelScope
    IModel iModel(  Lazy<ModelMqlBased> modelMqlBased,  //lazy-injection here!
            ModelFileBased modelFileBased,
            @Named("configClientType")String clientType) {
        switch (clientType) {
        case "mqlBot": 
            return modelMqlBased.get();
        case "fileBot":
                return modelFileBased;
        default:
            throw new RuntimeException();
        }
    }
}

以下代码应该是不相关的(关键是ModelModule),但是为了完成任务:

代码语言:javascript
复制
@ModelScope
public class ModelMqlBased implements IModel {

    @Inject
    public ModelMqlBased( Lazy<Mt5Painter> mt5Painter) {
        super();
        this.mt5Painter = mt5Painter.get();
    }

}

//this one sits in a "higher-scoped" component
@ClientScope
public class Mt5Painter {

    private IModel htfModel;
    private IModel ltfModel;

    @Inject
    public Mt5Painter(@Named("htfModel") Lazy<IModel> htfTradeModel, @Named("ltfModel") Lazy<IModel> ltfTradeModel) {
        super();
        this.htfModel = htfTradeModel.get();
        this.ltfModel = ltfTradeModel.get();
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-08 22:03:14

Lazy<T>并不意味着“稍后确定T是否绑定”,它意味着“确保在编译时为T存在绑定,但只在我调用get之后在运行时创建一个实例”。您仍然需要使T的绑定在所有情况下都可用,但是Dagger在明确要求之前不会尝试创建它的实例。

Dagger要求对于Provider<T>Lazy<T>的所有使用,绑定T都需要在编译时存在,即使在运行时您没有调用它。这确保了如果您确实在提供者或延迟实例上调用get(),它不会在运行时失败,因为它知道在编译时丢失了一个绑定。(懒散的行为与提供程序的行为完全相同,但Lazy会记住它返回的实例,而不管绑定是否限定了作用域。)

这意味着您的选项之一是为ModelMqlBased添加一个绑定,该绑定返回null或抛出异常,这在Dagger中通常是一个糟糕的想法,但对于您在运行时知道从来不调用提供方法的情况来说,这就足够了。

另一种实现所需灵活性的方法是使用@BindsOptionalOf。这允许您注入一个Optional<T>Optional<Lazy<T>>,如果绑定存在,则该值解析为现值,如果绑定不存在,则注入一个缺席占位符。

代码语言:javascript
复制
@Module
public abstract class ModelModule {
    // Note abstract class and static/abstract methods.

    @BindsOptionalOf
    abstract ModelMqlBased bindOptionalOfModelMqlBased();

    @Provides
    @ModelScope
    static IModel iModel(Optional<ModelMqlBased> modelMqlBased,
            ModelFileBased modelFileBased,
            @Named("configClientType")String clientType) {
        switch (clientType) {
        case "mqlBot": 
            return modelMqlBased.get();
        case "fileBot":
            return modelFileBased;
        default:
            throw new RuntimeException();
        }
    }
}

这可能使重用模块变得更容易,特别是因为(像多绑定一样)您可以提供任意数量的@BindsOptionalOf abstract T bindOptionalOfT();方法,而且Dagger不会抱怨重复。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55577658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档