Dagger2中的组件中不能有相同类型的提供者:@Inject标注的构造函数和module中标注的@Provides的方法,否则就会出现依赖迷失的错误。通过使用Qualifier可以实现提供相同类型的不同实例。
@Qualifier是javax.inject下定义的一个注解类,可以用在其他注解上:
package javax.inject;
//***
@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Qualifier {
}
@Named:
Dagger2提供了一个@Named注解用来标注不同的实例:
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {
String value() default "";
}
具体的用法:使用@Named标记需要注入的实例;使用@Named标注module类中的生成方法。
BMWWheel:
public class BMWWheel implements IWheel {
@Inject
public BMWWheel() {
super();
}
//***
}
在BMW中注入两种IWheel:
public class BMW {
@Inject
public BMW() {
super();
}
@Inject
IWheel rainWheel;
@Inject
IWheel sandWheel;
}
在WheelModel中提供绑定两种IWheel:
@Module
abstract class WheelModel {
@Binds
abstract IWheel provideRainWheel(BMWWheel wheel);
@Binds
abstract IWheel provideSandWheel(BMWWheel wheel);
}
编译后会提示: [Dagger/DuplicateBindings] com.hero.IWheel is bound multiple times:
解决办法:给BMW中需要注入的两个实例和module类中的方法增加相应的@Named注解:
BMW:
public class BMW {
@Inject
public BMW() {
super();
}
@Inject
@Named("rain")
IWheel rainWheel;
@Inject
@Named("sand")
IWheel sandWheel;
}
WheelModel:
@Module
abstract class WheelModel {
@Binds
@Named("rain")
abstract IWheel provideRainWheel(BMWWheel wheel);
@Binds
@Named("sand")
abstract IWheel provideSandWheel(BMWWheel wheel);
}
通过增加@Named注解,就实现了注入相同类型的不同实例的依赖关系。
实现原理:主要在生成的DaggerCarComponent类中:
public final class DaggerCarComponent implements CarComponent {
//***
@Override
public BMW makeBmw() {
return injectBMW(BMW_Factory.newInstance());}
private BMW injectBMW(BMW instance) {
BMW_MembersInjector.injectRainWheel(instance, new BMWWheel());
BMW_MembersInjector.injectSandWheel(instance, new BMWWheel());
return instance;
}
//***
}
可以看到,创建新的BMW实例时,会调用不同的注入对象的方法给不同的变量赋值。
BMW_MembersInjector:
public final class BMW_MembersInjector implements MembersInjector<BMW> {
@Override
public void injectMembers(BMW instance) {
injectRainWheel(instance, rainWheelProvider.get());
injectSandWheel(instance, sandWheelProvider.get());
}
@InjectedFieldSignature("com.hero.BMW.rainWheel")
@Named("rain")
public static void injectRainWheel(BMW instance, IWheel rainWheel) {
instance.rainWheel = rainWheel;
}
@InjectedFieldSignature("com.hero.BMW.sandWheel")
@Named("sand")
public static void injectSandWheel(BMW instance, IWheel sandWheel) {
instance.sandWheel = sandWheel;
}
}
自定义@Qualifier
自定义@Rain和@Sand两个注解:
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Rain {
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Sand {
}
在BMW中需要注入的变量上使用:
public class BMW {
@Inject
public BMW() {
super();
}
@Inject
@Rain
IWheel rainWheel;
@Inject
@Sand
IWheel sandWheel;
}
在module类中提供依赖的方法上使用:
@Module
abstract class WheelModel {
@Binds
@Rain
abstract IWheel provideRainWheel(BMWWheel wheel);
@Binds
@Sand
abstract IWheel provideSandWheel(BMWWheel wheel);
}
实现的效果与@Named类似,BMW中的两个相同类型的变量都得到了依赖注入。
实现原理与@Named类似,Dagger2生成的成员变量注入类会生成不同的方法来完成对应的变量注入。
如果module类中不使用@Binds而是@Provides,是否会有不同:
@Module
public class WheelModel {
@Provides
@Rain
public IWheel provideRainWheel() {
return new BMWWheel();
}
@Provides
@Sand
public IWheel provideSandWheel(BMWWheel wheel) {
return new BMWWheel();
}
}
变量注入的过程是跟@Binds没有区别:
public final class DaggerCarComponent implements CarComponent {
//***
private IWheel getSandIWheel() {
return WheelModel_ProvideSandWheelFactory.provideSandWheel(wheelModel, new BMWWheel());}
@Override
public BMW makeBmw() {
return injectBMW(BMW_Factory.newInstance());}
private BMW injectBMW(BMW instance) {
BMW_MembersInjector.injectRainWheel(instance, WheelModel_ProvideRainWheelFactory.provideRainWheel(wheelModel));
BMW_MembersInjector.injectSandWheel(instance, getSandIWheel());
return instance;
}
//***
}
只是依赖提供的方式不太一样,Dagger2为每个@Provides方法提供了对应的工厂类用来提供对象实例:
public final class WheelModel_ProvideRainWheelFactory implements Factory<IWheel> {
private final WheelModel module;
public WheelModel_ProvideRainWheelFactory(WheelModel module) {
this.module = module;
}
@Override
public IWheel get() {
return provideRainWheel(module);
}
public static WheelModel_ProvideRainWheelFactory create(WheelModel module) {
return new WheelModel_ProvideRainWheelFactory(module);
}
public static IWheel provideRainWheel(WheelModel instance) {
return Preconditions.checkNotNull(instance.provideRainWheel(), "Cannot return null from a non-@Nullable @Provides method");
}
}
WheelModel_ProvideRainWheelFactory用来创建被@Rain标注的BMWWheel实例
public final class WheelModel_ProvideSandWheelFactory implements Factory<IWheel> {
private final WheelModel module;
private final Provider<BMWWheel> wheelProvider;
public WheelModel_ProvideSandWheelFactory(WheelModel module, Provider<BMWWheel> wheelProvider) {
this.module = module;
this.wheelProvider = wheelProvider;
}
@Override
public IWheel get() {
return provideSandWheel(module, wheelProvider.get());
}
public static WheelModel_ProvideSandWheelFactory create(WheelModel module,
Provider<BMWWheel> wheelProvider) {
return new WheelModel_ProvideSandWheelFactory(module, wheelProvider);
}
public static IWheel provideSandWheel(WheelModel instance, BMWWheel wheel) {
return Preconditions.checkNotNull(instance.provideSandWheel(wheel), "Cannot return null from a non-@Nullable @Provides method");
}
}
WheelModel_ProvideSandWheelFactory用来创建被@Sand标注的BMWWheel实例。