前言
在《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