Dagger2 中自定义@Scope是如何实现生命周期绑定的

xiaoxiao2021-02-28  33

Dagger2 中自定义@Scope是如何实现生命周期绑定的

    其实Dagger2中我们自定自定义的Scope,例如@ActivityScope, @FragmentScope,其命名对于Dagger来说没有任何意义,其具体实现声明周期绑定也和我们的命名没有关系。其实现的机制如下:

    假设我们有一个SubComponent 叫做UserComponent,并且我们为其定义了自定Scope @Test, dagger编译过后会产生代码如下:

    

private final class UserComponentImpl implements UserComponent { //... private UserComponentImpl(UserModule userModule) { if (userModule == null) { throw new NullPointerException(); } this.userModule = userModule; initialize(); } private void initialize() { this.provideUserProvider = DoubleCheck.provider(UserModule_ProvideUserFactory.create(userModule)); this.provideRepositoriesManagerProvider = DoubleCheck.provider(UserModule_ProvideRepositoriesManagerFactory.create(userModule, provideUserProvider, DaggerAppComponent.this.provideGithubApiServiceProvider)); } //... }

UserComponentImpl对象是在UserComponentBuilder中被创建的。我们编译器在查询到有自定义Scope后,就会通过DoubleCheck来将我们正常获取注入实例的各项Factory进行封装包裹。那么为什么这么干呢?我们继续看DoubleCheck的源码:

public final class DoubleCheck<T> implements Provider<T>, Lazy<T> { private static final Object UNINITIALIZED = new Object(); private volatile Provider<T> provider; private volatile Object instance = UNINITIALIZED; private DoubleCheck(Provider<T> provider) { assert provider != null; this.provider = provider; } @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; } /** 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); } /** Returns a {@link Lazy} that caches the value from the given provider. */ public static <T> Lazy<T> lazy(Provider<T> provider) { if (provider instanceof Lazy) { @SuppressWarnings("unchecked") final Lazy<T> lazy = (Lazy<T>) provider; // Avoids memoizing a value that is already memoized. // NOTE: There is a pathological case where Provider<P> may implement Lazy<L>, but P and L // are different types using covariant return on get(). Right now this is used with // DoubleCheck<T> exclusively, which is implemented such that P and L are always // the same, so it will be fine for that case. return lazy; } return new DoubleCheck<T>(checkNotNull(provider)); } }

DoubleCheck通过其静态方法provider 返回了一个DoubleCheck对象,并且里面包含有factory,并通过get()方法返回在本生命周期里面的同一个实例。这个DoubleCheck对象由于是在UserComponent 这个SubComponent里面创建的,因此和UserComponent的生命周期是强绑定的,当UserComponent被回收时,DoubleCheck对象也会被回收。

整体的结构应该是 Activity/Fragment--创建新的-->SubComponent--编译产生-->SubComponentBuilder--注入model并传给-->SubComponentImpl-->通过Factory获取相关注入对象。 因此当 Activity/Fragment被销毁,后面后续的对象都会被销毁。

可参考相关博客:http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/

转载请注明原文地址: https://www.6miu.com/read-2150104.html

最新回复(0)