dagger2——@Singleton

·  阅读 179

给@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对象是同一个。

分类:
Android
标签:
分类:
Android
标签: