我面临的问题是我有一个基类和多个子类。为了解析特定的子类,我在Dagger 2中使用@Named注释。我想要实现的是如果我使用@Named(“Child3”)注入并且没有提供@Named(“Child3”)那么我应该默认情况下获取Base类的实例。
public class BaseClass {
public void haveFun(){
System.out.print("Having fun base");
}
}
public class Child1 extends BaseClass {
@Override
public void haveFun() {
System.out.print("Having fun Child1");
}
}
public class Child2 extends BaseClass {
@Override
public void haveFun() {
System.out.print("Having fun Child2");
}
}
现在在模块中我提供了这样的对象:
@Provides
@Named("Child1")
static BaseClass provideChild1(){
return new Child1();
}
@Provides
@Named("Child2")
static BaseClass provideChild2(){
return new Child2();
}
@Provides
static BaseClass provideBaseClass(){
return new BaseClass();
}
现在,在我的活动中,我正在注射:
public class ReceiptActivity extends AppCompatActivity {
@Inject @Named("Child1") BaseClass child1;
@Inject @Named("Child2") BaseClass child2;
@Inject @Named("Child3") BaseClass child3;
由于没有提供@Named(“Child3”),因此存在编译时错误,但我想要的是如果@Named(“Child3”)不在那里我应该得到BaseClass实例。 我怎样才能做到这一点?
答案 0 :(得分:1)
不幸的是,限定绑定(使用限定符注释的绑定,如@Named
)实际上没有回退或默认值。每个绑定都是不同的,并且不认为不同的绑定是相关的。这使得很难像你要求的那样编写回退逻辑。
这也是有道理的:尽管共享基类型,@Named("Porsche") Engine
和@Named("Lawnmower") Engine
永远不会真正替代彼此。它们是完全不同的依赖项,如果你错过了@Named("Porsche") Engine
,Dagger会遵循它应该在编译时失败的策略,而不是为了找不匹配或不合格的引擎。 / p>
相比之下,您可以绑定地图或使用Multibindings来表示您正在寻找的可替代性或灵活性。你不是注入绑定本身,而是注入一个Map,或者注入一个封装地图的Factory并为你拉出正确的绑定。
// This uses Multibindings, but you could manually create a Map instead.
@Binds @IntoMap @StringKey("Child1")
abstract BaseClass provideChild1(Child1 child1);
@Binds @IntoMap @StringKey("Child2")
abstract BaseClass provideChild2(Child2 child2);
// Then in your consumer...
@Inject Map<String, BaseClass> mapOfBaseClasses;
@Inject BaseClass baseClass;
// Or make an injectable Factory:
public class YourClassFactory {
private final Map<String, Provider<BaseClass>> baseClassMap;
private final Provider<BaseClass> baseClassProvider;
@Inject public YourClassFactory(/* ... */) { /* set fields */ }
public BaseClass get(String key) { /* write fallback logic here */ }
}
如果您有可能存在或不存在的特定绑定,您还可以使用@BindsOptionalOf
指示在编译时允许绑定丢失,然后您可以在运行时检测它。
@BindsOptionalOf @Named("Child3")
abstract BaseClass provideOptionalOfChild3();
// Then in your consumer:
private final BaseClass baseClass;
@Inject public YourConsumer(
@Named("Child3") Optional<BaseClass> optionalChild3,
Provider<BaseClass> defaultBaseClass) {
baseClass =
optionalChild3.isPresent()
? optionalChild3.get()
: defaultBaseClass.get();
}