给@Module中的方法增加@Singleton注解
那么Dagger会保证每次只会使用同一个实例。(@Componet的接口也需要增加@Singleton注解,否则编译会报错)。
WheelModel:
@Module
public class WheelModel {
@Provides
@Singleton
public static IWheel provideBMWWheel(){
return new BMWWheel();
}
}
CarComponent:
@Component(modules = WheelModel.class)
@Singleton
public interface CarComponent {
BMW makeBmw();
}
生成的WheelModel_ProvideBMWWheelFactory和BMW_MembersInjector与不加@Singleton并没有区别,区别在DaggerCarComponent:
public final class DaggerCarComponent implements CarComponent {
private Provider<IWheel> provideBMWWheelProvider;
private DaggerCarComponent() {
initialize();
}
public static Builder builder() {
return new Builder();
}
public static CarComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize() {
this.provideBMWWheelProvider = DoubleCheck.provider(WheelModel_ProvideBMWWheelFactory.create());
}
@Override
public BMW makeBmw() {
return injectBMW(BMW_Factory.newInstance());}
private BMW injectBMW(BMW instance) {
BMW_MembersInjector.injectWheel(instance, provideBMWWheelProvider.get());
return instance;
}
public static final class Builder {
private Builder() {
}
/**
* @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
*/
@Deprecated
public Builder wheelModel(WheelModel wheelModel) {
Preconditions.checkNotNull(wheelModel);
return this;
}
public CarComponent build() {
return new DaggerCarComponent();
}
}
}
可以看到DaggerCarComponent在构造时,会初始化生成一个provideBMWWheelProvider变量,它的作用是为构造BMW的对象注入IWheel对象。而provideBMWWheelProvider是一个DoubleCheck类型的变量,具体的作用是在调用get()方法获取一个对象实例时,会判断是否已经生成,如果已经创建,则直接返回,否则会创建新的对象实例。通过这个DoubleCheck实现了IWheel对象的唯一性。
DoubleCheck的**get()**方法:
public T get() {
Object result = instance;
if (result == UNINITIALIZED) {
synchronized (this) {
result = instance;
if (result == UNINITIALIZED) {
result = provider.get();
instance = reentrantCheck(instance, result);
/* Null out the reference to the provider. We are never going to need it again, so we
* can make it eligible for GC. */
provider = null;
}
}
}
return (T) result;
}
使用结果:
public static void main(String[] args) {
CarComponent component = DaggerCarComponent.create();
System.out.println(component.makeBmw().wheel);
System.out.println(component.makeBmw().wheel);
}
可以看到虽然创建了两个BMW对象,但是它们的wheel对象是同一个,符合“单例”的特性。
注:
@Singleton并不是常规理解的单例,即全局都只有一个,它是有作用域的,在上面的例子中,是只在同一个@Componet注解的类的对象实例中才有效。如果创建了不同的@Componet对象,那么就不能共享同一个实例。如:
public static void main(String[] args) {
System.out.println(DaggerCarComponent.create().makeBmw().wheel);
System.out.println(DaggerCarComponent.create().makeBmw().wheel);
}
在这种场景下,创建了两个DaggerCarComponent对象实例,那么WheelModel的**provideBMWWheel()**生成的对象实例并不能共享。
给某个类增加@Singleton注解
@Singleton
public class BMW {
@Inject
public BMW(){
super();
}
@Inject
IWheel wheel;
}
那么实际的效果是,同一个Componet对象创建的BMW实例都是同一个,具体的实现如下:
生成的BMW_Factory与不加@Singleton注解是一样的。
不同之处还是在于DaggerCarComponent,这也说明了@Singleton的作用域在Componet内:
public final class DaggerCarComponent implements CarComponent {
private Provider<BMW> bMWProvider;
private DaggerCarComponent() {
initialize();
}
public static Builder builder() {
return new Builder();
}
public static CarComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize() {
this.bMWProvider = DoubleCheck.provider(BMW_Factory.create(WheelModel_ProvideBMWWheelFactory.create()));
}
@Override
public BMW makeBmw() {
return bMWProvider.get();}
public static final class Builder {
private Builder() {
}
/**
* @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
*/
@Deprecated
public Builder wheelModel(WheelModel wheelModel) {
Preconditions.checkNotNull(wheelModel);
return this;
}
public CarComponent build() {
return new DaggerCarComponent();
}
}
}
可以看到,为了共享BMW对象,DaggerCarComponent也使用了DoubleCheck这种方式,确保每次获取到的BMW对象是同一个。