Dagger2 研习(一)

前言

    在《Dagger2 使用(一)》中我们一步步深入知道了dagger的使用。本文主要从dagger源码角度来分析为什么。相互对比印证,相信总会有所收获。

    另外,说是源码,其实关于processor部分这里并没有分析,而是直接分析自动生成后的代码。

    为了减少篇幅和重复,需要和 《Dagger2 使用(一)》对照阅读。

引例

    在《Dagger2 使用》前言部分,我们通过一个例子来引入dagger的核心功能。现在我们从代码角度分析,dagger到底是如何完成这个注入过程的。

    首先,需要被注入的类是Car(有使用@Inject的字段),那么dagger就会为其生成一个辅助类

public final class Car_MembersInjector implements MembersInjector<Car> {
  private final Provider<Chair> mChainProvider;

  private final Provider<Wheel> mWheelProvider;

  public Car_MembersInjector(Provider<Chair> mChainProvider, Provider<Wheel> mWheelProvider) {
    assert mChainProvider != null;
    this.mChainProvider = mChainProvider;
    assert mWheelProvider != null;
    this.mWheelProvider = mWheelProvider;
  }

  public static MembersInjector<Car> create(
      Provider<Chair> mChainProvider, Provider<Wheel> mWheelProvider) {
    return new Car_MembersInjector(mChainProvider, mWheelProvider);
  }

  @Override
  public void injectMembers(Car instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mChain = mChainProvider.get();
    instance.mWheel = mWheelProvider.get();
  }

  public static void injectMChain(Car instance, Provider<Chair> mChainProvider) {
    instance.mChain = mChainProvider.get();
  }

  public static void injectMWheel(Car instance, Provider<Wheel> mWheelProvider) {
    instance.mWheel = mWheelProvider.get();
  }
}

    基类是 MembersInjector<T> ,该类只有一个方法,就是injectMember(T instance) 用来进行注入赋值。其实这个类非常浅显。不管是通过create创建还是通过构造函数创建,然后调用injectMembers注入,还有直接调用injectXXX注入某个对象,都会需要提供Provider<X>对象。关于Provider下面会有介绍,如果简单理解,它其实就算是一个工厂,提供get方法。当调用get方法之后会进行对象生产。

    总结来说,dagger会对需要被注入的对象生成一个XXX_MemberInjector对象,传入Provider,在需要注入的时候,调用get生产对象。它本身只负责注入,不负责生产

    然后是整个注入流程,就是这句话

public void inject(){
        CarComponent carComponent = DaggerCarComponent.builder().chairModule(new ChairModule()).build();
        carComponent.inject(this);
    }

        DaggerCarComponent是根据CarComponet自动生成的一个类,继承与CarComponent。它其中会包含一个Builder的内部类,存储/赋值CarComponent中所有声明需要的module模块。

public static final class Builder {
    private ChairModule chairModule;

    private Builder() {}

    public CarComponent build() {
      if (chairModule == null) {
        this.chairModule = new ChairModule();
      }
      return new DaggerCarComponent(this);
    }

    public Builder chairModule(ChairModule chairModule) {
      this.chairModule = Preconditions.checkNotNull(chairModule);
      return this;
    }
  }

    注意build方法,如果我们没有调用chairModule 赋值,他会自动调用new ChairModule()。所以这也就是解释了为什么module如果存在默认构造函数,可以省略,dagger自动帮我们注入的原因。

public final class DaggerCarComponent implements CarComponent {
  private Provider<Chair> provideChairProvider;

  private MembersInjector<Car> carMembersInjector;

  private DaggerCarComponent(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  ........

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.provideChairProvider = ChairModule_ProvideChairFactory.create(builder.chairModule);

    this.carMembersInjector =
        Car_MembersInjector.create(provideChairProvider, Wheel_Factory.create());
  }

  @Override
  public Car inject(Car car) {
    carMembersInjector.injectMembers(car);
    return car;
  }

  .........
}

    DaggerXXXComponent 会把他包含的 module 所有提供的对象(@Provides注解方法)生成一个Provider<T> 对象。 

     因为CarComponent需要对Car进行注入,所以会包含一个Car_MembersInjector 成员变量。当我们调用inject方法 进行注入的时候,实际上就是调用该成员变量的injectMembers进行注入。

    所有问题的关键就在于对成员变量的初始化,也就是在方法initialize方法中。首先是Provider<T>对象,所有在Module中使用@Provides注解的方法,都会生成一个对应的类,类名就是  

                        Module名_方法名Factory

    由于我们在ChairModule中有一个provideChair方法,用来提供Chair,所有生成了一个ChairModule_ProvideChairFactory类。

public final class ChairModule_ProvideChairFactory implements Factory<Chair> {
  private final ChairModule module;

  public ChairModule_ProvideChairFactory(ChairModule module) {
    assert module != null;
    this.module = module;
  }

  @Override
  public Chair get() {
    return Preconditions.checkNotNull(
        module.provideChair(), "Cannot return null from a non-@Nullable @Provides method");
  }

  public static Factory<Chair> create(ChairModule module) {
    return new ChairModule_ProvideChairFactory(module);
  }
}

    首先该类继承与 Factory<T> , 我们之前说Provider<T>相当于工厂,其实有点错误,应该是Factory相当于Provider,因为这里Factory<T> 其实就是继承了Provider<T>

    不管是调用create或者构造方法,都需要传入源module对象。在DaggerCarComponent中,调用了create方法(module我们已经在build中赋值了),创建了一个ChairModule_ProvideChairFactory对象,由于它继承与Factory<Chair>,进一步继承与Provider<Chair>,所有赋值给成员变量没问题。

    然后将这个provider<Chair>当做参数,用于构建Car_MembersInjector,当 Car_MembersInjector 调用injectMembers进行注入时,会调用provider<Chair>的get方法,也就是调用ChairModule_ProvideChairFactory的get方法。

    该get方法就是调用源module中相应的 @Provides 方法,获取真正的注入对象。

    以上就是全部的基本流程。

注入变异1

    对应dagger使用的变异1,我们没有提供WheelModule,也没有@Provides用来提供Wheel对象,他的注入是如何完成的?

    首先我们需要在Wheel的某个构造方法上使用@Inject,这个时候,dagger就会自动生成一个Wheel_Factory类

public final class Wheel_Factory implements Factory<Wheel> {
  private static final Wheel_Factory INSTANCE = new Wheel_Factory();

  @Override
  public Wheel get() {
    return new Wheel();
  }

  public static Factory<Wheel> create() {
    return INSTANCE;
  }
}

    首先它是一个单例的类。除此之外,和    ChairModule_ProvideChairFactory 基本相同。继承与Factory,调用get时,就会new一个Wheel 对象提供给外部。

    

注入变异2

    在Car中,去掉 Wheel成员变量的@Inject注解(不自动注入)。Car_MembersInjector中就少了一个成员变量,现在只注入Chair对象。

    对 CarComponent 修改后,新增 getWheel()方法。DaggerCarComponent中就自动实现了改接口

@Override
  public Wheel getWheel() {
    return new Wheel();
  }

    原理基本能想到,但是这种使用方法经常会被遗忘。

注入变异3

    首先shape会 自动生成一个Shape_Factory类,这个和上面介绍的一样。

   然后Wheel类自动生成的Wheel_Factory类由于需要参数,所以发生了变化,相比之前,多以个Provider<Shape>成员变量,需要在create或者改造函数中传入,然后在get方法中使用 get方法传入Wheel的构造函数,生成Wheel。

     在DaggerCarComponent中,initialize方法发生了改变

private void initialize(final Builder builder) {

    this.provideChairProvider = ChairModule_ProvideChairFactory.create(builder.chairModule);

    this.wheelProvider = Wheel_Factory.create(Shape_Factory.create());

    this.carMembersInjector = Car_MembersInjector.create(provideChairProvider, wheelProvider);
  }

    多了成员变量 Provider<Wheel> wheelProvider 这个不关键,因为没有在其他地方用到。

    相比之前直接Wheel_Factory.create()多了参数,参数也是通过Shape_Factory.create()自动生成。

    由此类推,如果Shape构造函数也需要参数,并且能够被注入,那么,生成Provider<Wheel> 的层级将会继续+1。

注入变异4

    我们修改了ChairModule,并且提供了Shape,所以会自动生成一个ChairModule_ProvideShapeFactory的类(上面有介绍。)

    在DaggerCarComponent中,initialize方法发生了变化。

 private void initialize(final Builder builder) {

    this.provideChairProvider = ChairModule_ProvideChairFactory.create(builder.chairModule);

    this.provideShapeProvider = ChairModule_ProvideShapeFactory.create(builder.chairModule);

    this.wheelProvider = Wheel_Factory.create(provideShapeProvider);

    this.carMembersInjector = Car_MembersInjector.create(provideChairProvider, wheelProvider);
  }

    其实和以上几个变异并没有多少区别,所以是不是大概可以总结出一个规律,只要是在DaggerCarComponent中能够找到生成对象所需要的所有组件,那么这个对象就能够被注入!

@Qualifier

    该标注实际上在生成后的代码中是并没有提现的,甚至该注解标注的自定义注解也不会出现在dagger生成后的代码中。

    那么它是在哪里起作用的呢?答案是在processor中起作用,用来对注入进行对象的配对。由于本文叙述processor的代码内容,所以这里它具体的实现逻辑就不分析了。

Component 之 dependencies

    首先是BeanComponent, 和普通的component没有区别,还是按照上述规则生成代码。差别就在MainComponent生成的代码中。

public static final class Builder {
    private BeanComponent beanComponent;

    private Builder() {}

    public MainComponent build() {
      if (beanComponent == null) {
        throw new IllegalStateException(BeanComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerMainComponent(this);
    }

    public Builder beanComponent(BeanComponent beanComponent) {
      this.beanComponent = Preconditions.checkNotNull(beanComponent);
      return this;
    }
  }

    首先是Builder中,这里需要手动注入BeanComponent,否则报错,这个和能够省略的Module有点区别。

 private void initialize(final Builder builder) {

    this.getBeanTypeAProvider =
        new com_guardz_dagger2demo_demo4_BeanComponent_getBeanTypeA(builder.beanComponent);

    this.getBeanTypeBProvider =
        new com_guardz_dagger2demo_demo4_BeanComponent_getBeanTypeB(builder.beanComponent);

    this.userMembersInjector =
        User_MembersInjector.create(
            getBeanTypeAProvider, getBeanTypeBProvider, RealObj_Factory.create());
  }

     总的来说initialize方法还是中规中矩,它的最终目标就是生成一个MembersInjector,不同只在于凑齐它的参数的方法。

    这里dagger使用了一个没有出现过的类,来当做Provider<T>。那么该类必须要继承Provider<T>,并且能够在get的时候正确的返回对象。

    看一下该类

private static class com_guardz_dagger2demo_demo4_BeanComponent_getBeanTypeA
      implements Provider<BeanTypeA> {
    private final BeanComponent beanComponent;

    com_guardz_dagger2demo_demo4_BeanComponent_getBeanTypeA(BeanComponent beanComponent) {
      this.beanComponent = beanComponent;
    }

    @Override
    public BeanTypeA get() {
      return Preconditions.checkNotNull(
          beanComponent.getBeanTypeA(), "Cannot return null from a non-@Nullable component method");
    }
  }

    类完全没有难度,接受一个BeanComponent参数,在调用get的时候实际上就是调用BeanComponent中的相应方法。

    这就解释了为什么BeanComponent必须要向外声明自己能够提供的内容:

                根据对外声明的内容,dagger会自动生成一个继承与Provider<T>的类

                在真正需要注入对象的时候,实际上是通过被依赖的Component所暴露的方法来获取这个对象                   的。

@SubComponent

    这里我们分析简单的一重关联,因为多重关联其实和一重关联原理一样。

    对于被标注为Subcomponent的 BComponent而言,dagger并不会为其生成DaggerBComponent这么一个类,所有的实现都是在最上层的Component中实现的,也就是AComponent。

    DaggerAComponent的其他方法都没有变,只是多了一个

@Override
  public BComponent getBComponent(BModule bModule) {
    return new BComponentImpl(bModule);
  }

    该方法返回简单BComponentImpl类实例

private final class BComponentImpl implements BComponent {
    private final BModule bModule;

    private Provider<SomeClassB> providerSomeClassBProvider;

    private MembersInjector<User> userMembersInjector;

    private BComponentImpl(BModule bModule) {
      this.bModule = Preconditions.checkNotNull(bModule);
      initialize();
    }

    @SuppressWarnings("unchecked")
    private void initialize() {

      this.providerSomeClassBProvider = BModule_ProviderSomeClassBFactory.create(bModule);

      this.userMembersInjector =
          User_MembersInjector.create(
              providerSomeClassBProvider, DaggerAComponent.this.provideSomeClassAProvider);
    }

    @Override
    public void inject(User user) {
      userMembersInjector.injectMembers(user);
    }
  }

    注:假设我们存在User类,需要注入SomeClassA和SomeClassB。

    我们可以发现BComponentImpl其实和 DaggerBComponent很像(虽然没有生成,但是如果根据生成原则推算的话),最主要的还是initialize方法。

    区别就是,它是一个内部类,当我们需要生成一个User_MembersInjector的时候,它需要一个生成SomeClassA的provider,BComponent本身没提供,但是它的外部类(AComponent)提供了啊,直接用!        以上就是@Subcomponent实现的原理。

@Singleton

    @Singleton用来表示单例,但是仅仅是在Component的生命周期中单例。

    查看dagger自动生成的代码,发现Module根本就没有发生变化,变化发生在了

@SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.provideChairProvider = ChairModule_ProvideChairFactory.create(builder.chairModule);

    this.provideShapeProvider =
        DoubleCheck.provider(ChairModule_ProvideShapeFactory.create(builder.chairModule));

    this.wheelProvider = Wheel_Factory.create(provideShapeProvider);

    this.carMembersInjector = Car_MembersInjector.create(provideChairProvider, wheelProvider);
  }

    provideShapeProvider的获取方法和原先有了些差别,我们将ChairModule_ProvideShapeFactory进行了再次封装,放入了DoubleCheck中,所以我们可以想象,单例的实现就是靠DoubleCheck来实现的。

    来看下DoubleCheck.provider方法。

  /** Returns a {@link Provider} that caches the value from the given delegate provider. */
  public static <T> Provider<T> provider(Provider<T> delegate) {
    checkNotNull(delegate);
    if (delegate instanceof DoubleCheck) {
      /* This should be a rare case, but if we have a scoped @Binds that delegates to a scoped
       * binding, we shouldn't cache the value again. */
      return delegate;
    }
    return new DoubleCheck<T>(delegate);
  }

    实际上就是new了一个DoubleCheck(我们的Provider并不是DoubleCheck,而是一个Factory)。

  private DoubleCheck(Provider<T> provider) {
    assert provider != null;
    this.provider = provider;
  }

    构造方法也只是将ChairModule_provideShapeFactory的实例存入provider的变量中。关键是get方法

  @SuppressWarnings("unchecked") // cast only happens when result comes from the provider
  @Override
  public T get() {
    Object result = instance;
    if (result == UNINITIALIZED) {
      synchronized (this) {
        result = instance;
        if (result == UNINITIALIZED) {
          result = provider.get();
          /* Get the current instance and test to see if the call to provider.get() has resulted
           * in a recursive call.  If it returns the same instance, we'll allow it, but if the
           * instances differ, throw. */
          Object currentInstance = instance;
          if (currentInstance != UNINITIALIZED && currentInstance != result) {
            throw new IllegalStateException("Scoped provider was invoked recursively returning "
                + "different results: " + currentInstance + " & " + result + ". This is likely "
                + "due to a circular dependency.");
          }
          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;
  }

    为什么叫DoubleCheck,因为他会进行双重检测(result == UNINITIALIZED),其中单例模式的实现方法中,有种就叫做双重检测法。

    所以,为什么我们的单例仅仅是在一个Component的声明中其中?因为Component并不是单例,所以每次创建Component都会创建一个DoubleCheck 的 Provider,而DoubleCheck只能保证在同一个对象中,多次调用get返回同一个对象。

@Scope

    例子中,最不可思议的地方就在于同一个Component提供的对象拥有不同的生命周期,我们来看一下它的原理。

public final class DaggerApplicationComponent implements ApplicationComponent {
  private Provider<ClassApplication> getClassApplicationProvider;

  .......

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.getClassApplicationProvider =
        DoubleCheck.provider(
            ApplicationModule_GetClassApplicationFactory.create(builder.applicationModule));
  }

  @Override
  public UserComponent getUserComponent(UserModule userModule) {
    return new UserComponentImpl(userModule);
  }

  .....

  private final class UserComponentImpl implements UserComponent {
    private final UserModule userModule;

    private Provider<ClassUser> getClassUserProvider;

    ......

    @SuppressWarnings("unchecked")
    private void initialize() {

      this.getClassUserProvider =
          DoubleCheck.provider(UserModule_GetClassUserFactory.create(userModule));
    }

    @Override
    public ClassApplication getClassApplication() {
      return DaggerApplicationComponent.this.getClassApplicationProvider.get();
    }

    @Override
    public ClassUser getClassUser() {
      return getClassUserProvider.get();
    }

    @Override
    public ActivityComponent getActivityComponent(ActivityModule activityModule) {
      return new ActivityComponentImpl(activityModule);
    }

    private final class ActivityComponentImpl implements ActivityComponent {
      private final ActivityModule activityModule;

      private Provider<ClassActivity> getClassActivityProvider;

      ......

      @SuppressWarnings("unchecked")
      private void initialize() {

        this.getClassActivityProvider =
            DoubleCheck.provider(ActivityModule_GetClassActivityFactory.create(activityModule));
      }

      @Override
      public ClassApplication getClassApplication() {
        return DaggerApplicationComponent.this.getClassApplicationProvider.get();
      }

      @Override
      public ClassActivity getClassActivity() {
        return getClassActivityProvider.get();
      }

      @Override
      public ClassUser getClassUser() {
        return UserComponentImpl.this.getClassUserProvider.get();
      }
    }
  }
}

    用到的技巧和Subcomponent一样,都是内部对象能够调用外部对象的字段这么个道理。

    所有的UserComponent都使用同一个DaggerComponent来返回ClassApplication。

@Reusable 

    当我们在一个@Provides上使用了这个标记,那么在对应的Component中代码是这样的

 @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.providerChineseNameProvider =
        SingleCheck.provider(NameModule_ProviderChineseNameFactory.create(builder.nameModule));

    this.providerForeignerNameProvider =
        NameModule_ProviderForeignerNameFactory.create(builder.nameModule);

    this.personMembersInjector =
        Person_MembersInjector.create(providerChineseNameProvider, providerForeignerNameProvider);
  }

    使用了SingleCheck来生成provider。

public final class SingleCheck<T> implements Provider<T>, Lazy<T> {
  private static final Object UNINITIALIZED = new Object();

  private volatile Provider<T> provider;
  private volatile Object instance = UNINITIALIZED;

  private SingleCheck(Provider<T> provider) {
    assert provider != null;
    this.provider = provider;
  }

  @SuppressWarnings("unchecked") // cast only happens when result comes from the delegate provider
  @Override
  public T get() {
    // provider is volatile and might become null after the check to instance == UNINITIALIZED, so
    // retrieve the provider first, which should not be null if instance is UNINITIALIZED.
    // This relies upon instance also being volatile so that the reads and writes of both variables
    // cannot be reordered.
    Provider<T> providerReference = provider;
    if (instance == UNINITIALIZED) {
      instance = providerReference.get();
      // 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) instance;
  }

  /** Returns a {@link Provider} that caches the value from the given delegate provider. */
  public static <T> Provider<T> provider(Provider<T> provider) {
    // If a scoped @Binds delegates to a scoped binding, don't cache the value again.
    if (provider instanceof SingleCheck || provider instanceof DoubleCheck) {
      return provider;
    }
    return new SingleCheck<T>(checkNotNull(provider));
  }
}

    SingleCheck 和 DoubleCheck 很像,只是不在进行双重检测,也没有做多线程的处理。所以确实无法保证每次get到的一定是同一个对象。

@Lazy 和 @Provider

    对象中直接注入Lazy和Provider的实现原理其实和component和module并没有关系,差别产生在MembersInjector<T> 类中。

    例子中差别就在Car_MembersInjector,而且差别也仅仅在injectMembers方法中

  @Override
  public void injectMembers(Car instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mChain = DoubleCheck.lazy(mChainProvider);
    instance.mWheel = mWheelProvider;
  }

    原本我们会直接调用provider.get获取对象,并且赋值。但是这里不同,如果是provider类型,那就直接赋值provider,如果是lazy,那么会把provider包装成DoubleCheck返回(双重检测,保证返回同一个对象。)

    所以Privider<T>注入类型到底是不是单例还是取决于DaggerxxxComponent中的provider是不是单例,而Lazy<T>一定会被封装成单例。

    

可释放的引用(Releasable references)

    首先来看一下被注入的类,是如何注入ReleasableReferenceManager对象的

public Person_MembersInjector(
      Provider<Name> mForeignerNameProvider,
      Provider<ReleasableReferenceManager> mReleasableReferenceManagerProvider) {
         .....
}

    原理还是很简单的,就是在Person_MembersInjector类的构造函数时多了一个Provider对象(和其他需要被注入对象一样)。

    所以开看下这个Provider对象的生成过程

 private void initialize(final Builder builder) {

    ........

    this.providerForeignerNameProvider =
        ReferenceReleasingProvider.create(
            NameModule_ProviderForeignerNameFactory.create(builder.nameModule),
            releaseableTestReferences);

    this.forReleasableReferencesReleasableReferenceManagerProvider =
        new Provider<ReleasableReferenceManager>() {
          @Override
          public ReleasableReferenceManager get() {
            return releaseableTestReferences;
          }
        };

    this.personMembersInjector =
        Person_MembersInjector.create(
            providerForeignerNameProvider,
            forReleasableReferencesReleasableReferenceManagerProvider);
  }

    在DaggerXXXComponent中,使用了 @ReleaseableTest注解(一个使用了@CanReleaseReferences的@Scope)的对象,生成的Provider并不是普通@Scope的DoubleCheck,而是一个ReferenceReleasingProvider,并且传入了一个 ReferenceReleasingProviderManager 对象,同时将这个ReferenceReleasingProviderManager对象封装成一个Provider,最后传入Person_MembersInjector。

    所以关键问题就集中在了ReferenceReleasingProvider 和这个ReferenceReleasingProviderManager对象上。

    ReferenceReleasingProviderManager 继承与 ReleasableReferenceManager(就是需要注入的额外对象。)

private final ReferenceReleasingProviderManager releaseableTestReferences =
    new ReferenceReleasingProviderManager(ReleaseableTest.class);

    new倒是很简单,就是传入了ReleaseableTest的类。我们是如何使用它的?调用了releaseStrongReferences和 restoreStringReferences。

@Override
  public void releaseStrongReferences() {
    execute(Operation.RELEASE);
  }

  /**
   * {@inheritDoc} Calls {@link ReferenceReleasingProvider#restoreStrongReference()} on all
   * providers that have been {@linkplain #addProvider(ReferenceReleasingProvider) added} and that
   * are still weakly referenced.
   */
  @Override
  public void restoreStrongReferences() {
    execute(Operation.RESTORE);
  }

  private void execute(Operation operation) {
    Iterator<WeakReference<ReferenceReleasingProvider<?>>> iterator = providers.iterator();
    while (iterator.hasNext()) {
      ReferenceReleasingProvider<?> provider = iterator.next().get();
      if (provider == null) {
        iterator.remove();
      } else {
        operation.execute(provider);
      }
    }
  }

    遍历providers的队列,队列中存放了RefereceReleasingProvider的弱引用,获取RefereceReleasingProvider对象,并调用operation.execute,该方法实际上是调用了RefereceReleasingProvider对象自己的对应方法(releaseStrongReferences和 restoreStringReferences)。

    那么,对于ReferenceReleasingProviderManager 还有两个问题:

                    队列中的对象是什么时候放进去的。

                    为什么要在队列中放入弱引用

    首先第一个,当我们创建ReferenceReleasingProvider对象时,我们会调用它的create,并且传入一个ReferenceReleasingProviderManager。

public static <T> ReferenceReleasingProvider<T> create(
      Provider<T> delegate, ReferenceReleasingProviderManager references) {
    ReferenceReleasingProvider<T> provider =
        new ReferenceReleasingProvider<T>(checkNotNull(delegate));
    references.addProvider(provider);
    return provider;
  }

    看到,我们调用了addProvider,将数据存入了队列中。

    第二问题,说实话我也不知道,因为这里的ReferenceReleasingProvider同样会被保存在DaggerXXXComponent,所以在DaggerXXXComponent的生命周期中,一定是存在强引用的,所以也不会被回收。如果你知道原因,不妨留言告知,我会及时修正。

    刚才说到,ReferenceReleasingProviderManager实际上最终会调用ReferenceReleasingProvider对象的对应方法。

    在此之前,ReferenceReleasingProvider本身是一个Provider,并且在注入的时候回调用get来产生数据。

public T get() {
    Object value = currentValue();
    if (value == null) {
      synchronized (this) {
        value = currentValue();
        if (value == null) {
          value = provider.get();
          if (value == null) {
            value = NULL;
          }
          strongReference = value;
        }
      }
    }
    return value == NULL ? null : (T) value;
  }

  private Object currentValue() {
    Object value = strongReference;
    if (value != null) {
      return value;
    }
    if (weakReference != null) {
      return weakReference.get();
    }
    return null;
  }

    首先他也采用了双重检测,但是这个双重检测并不能保证单例(只有在stringReference不为空的时候才是单例),当强引用为空,弱引用为空时,就会再次调用provider.get方法来生成新对象。并且保存到stringReference。

public void releaseStrongReference() {
    Object value = strongReference;
    if (value != null && value != NULL) {
      synchronized (this) {
        @SuppressWarnings("unchecked") // values other than NULL come from the provider
        T storedValue = (T) value;
        weakReference = new WeakReference<T>(storedValue);
        strongReference = null;
      }
    }
  }

  /**
   * Restores the strong reference that was previously {@linkplain #releaseStrongReference()
   * released} if the {@link WeakReference} has not yet been cleared during garbage collection.
   */
  public void restoreStrongReference() {
    Object value = strongReference;
    if (weakReference != null && value == null) {
      synchronized (this) {
        value = strongReference;
        if (weakReference != null && value == null) {
          value = weakReference.get();
          if (value != null) {
            strongReference = value;
            weakReference = null;
          }
        }
      }
    }
  }

    释放强引用和重新储存强引用的代码都比较简单,无非是weakReference和stringReference相互赋值而已。

    但是发现一个问题,我们在调用get时,如果之前调用了releaseStringReference,然后弱引用又被GC掉了。这个时候再次调用了get,产生新对象。新对象会被存储在强引用中,如果如果想要节省内存,需要再次调用releaseStringReference,将强引用转换成弱引用。

    所以总结来说,releaseStringReference其实是一个一次性的工作,而不是一种状态

    以上就是releasable的所有内容。

 

 

 

 

 

 

 

 

Provider<T>  And  Lazy<T>

    Provider是JSR-330标准中定义的,需要注入器自己实现的类

    接口 Provider 用于提供类型 T 的实列。Provider 是一般情况是由注入器实现的。对于任何可注入的 T 而言,您也可以注入 Provider<T>。与直接注入 T 相比,注入 Provider<T> 使得:

  • 可以返回多个实例。

  • 实例的返回可以延迟化或可选

  • 打破循环依赖。

  • 可以在一个已知作用域的实例内查询一个更小作用域内的实例。

   例子:   
   class Car { 
       @Inject Car(Provider<Seat> seatProvider) { 
           Seat driver = seatProvider.get(); 
           Seat passenger = seatProvider.get(); 
           ... 
       } 
   }

    Lazy<T> 是dagger2自己实现的一个内容,类似于provider 也有类似的作用,两个的区别其实在Lazy这个类中的注释上已经有非常详细的描述,不过这里,我们先来看看两个类的实现,分别是DoubleCheck和SingleCheck

转载于:https://my.oschina.net/zzxzzg/blog/1539751

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值