gpt4 book ai didi

java - 如何使用 Dagger-2 延迟注入(inject)接口(interface)?

转载 作者:行者123 更新时间:2023-12-02 10:01:40 25 4
gpt4 key购买 nike

我遇到过 Dagger-2 不允许我延迟注入(inject)的情况。看来它仍然需要我在编译时提供对象。这是为什么?

堆栈跟踪:

[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()

堆栈跟踪代码:

//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),但为了完整起见:

@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();
}

最佳答案

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

Dagger 要求 Provider<T> 的所有用途都如此和Lazy<T> ,绑定(bind) T 需要在编译时存在,即使在运行时您不调用它。这确保了如果您确实调用 get()在 Provider 或 Lazy 实例上,它不会在运行时因它知道在编译时丢失的绑定(bind)而失败。 (Lazy 的行为与 Provider 完全相同,但 Lazy 会记住它返回的实例,无论绑定(bind)是否限定范围。)

这意味着您的选择之一是添加返回 null 的 ModelMqlBased 绑定(bind)。或抛出异常,这在 Dagger 中通常是一个糟糕的主意,但对于您在运行时知道永远不会调用 Provides 方法的情况来说,这就足够了。

实现您所寻求的灵 active 的另一种方法是使用 @BindsOptionalOf 。这允许您注入(inject) Optional<T>Optional<Lazy<T>> ,如果绑定(bind)存在,则解析为当前值;如果绑定(bind)不存在,则解析为不存在的占位符。

@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();
}
}
}

这可能会使重用模块变得更容易,特别是因为(如多重绑定(bind))您可以提供尽可能多的 @BindsOptionalOf abstract T bindOptionalOfT();方法如你所愿,Dagger 不会提示重复。

关于java - 如何使用 Dagger-2 延迟注入(inject)接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55577658/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com