经过了十来天的努力看代码写需求,成功的忘记了之前的博客写到哪了......
先接着上章所说的,讲一下全局单例的源代码。
代码如下
public final class DaggerSecondComponent implements SecondComponent { private ProviderprovideCoffeeProvider; private Provider globalProvider; private Provider provideToolsProvider; private MembersInjector secondActivityMembersInjector; private MembersInjector thridActivityMembersInjector; private DaggerSecondComponent(Builder builder) { assert builder != null; initialize(builder); } public static Builder builder() { return new Builder(); } @SuppressWarnings("unchecked") private void initialize(final Builder builder) { this.provideCoffeeProvider = SecondModule_ProvideCoffeeFactory.create(builder.secondModule); this.globalProvider = new Factory () { private final GlobalComponent globalComponent = builder.globalComponent; @Override public Global get() { return Preconditions.checkNotNull( globalComponent.global(), "Cannot return null from a non-@Nullable component method"); } }; this.provideToolsProvider = SecondModule_ProvideToolsFactory.create(builder.secondModule); this.secondActivityMembersInjector = SecondActivity_MembersInjector.create( provideCoffeeProvider, globalProvider, provideToolsProvider); this.thridActivityMembersInjector = ThridActivity_MembersInjector.create(provideCoffeeProvider, globalProvider); } @Override public void inject(SecondActivity activity) { secondActivityMembersInjector.injectMembers(activity); } @Override public void inject(ThridActivity activity) { thridActivityMembersInjector.injectMembers(activity); } public static final class Builder { private SecondModule secondModule; private GlobalComponent globalComponent; private Builder() {} public SecondComponent build() { if (secondModule == null) { this.secondModule = new SecondModule(); } if (globalComponent == null) { throw new IllegalStateException(GlobalComponent.class.getCanonicalName() + " must be set"); } return new DaggerSecondComponent(this); } public Builder secondModule(SecondModule secondModule) { this.secondModule = Preconditions.checkNotNull(secondModule); return this; } public Builder globalComponent(GlobalComponent globalComponent) { this.globalComponent = Preconditions.checkNotNull(globalComponent); return this; } } }
代码量有点让人头秃。。。。。。
不过我们能按照注入时的代码顺序捋一下:
DaggerSecondComponent.builder() .globalComponent(new MyApplication().get()) .secondModule(new SecondModule())//添加Module .build() .inject(this);
比起之前的注入代码,我们多写了个globalcomponent,所以我们的Builder类中也就多了一个方法,其实和之前的注入也差不多,只不过相当于写了两个Module。
但是到了initialize中就不一样了,我们可以看见个特立独行的方法:
this.globalProvider = new Factory() { private final GlobalComponent globalComponent = builder.globalComponent; @Override public Global get() { return Preconditions.checkNotNull( globalComponent.global(), "Cannot return null from a non-@Nullable component method"); } };
在这个方法中,给globalProvide赋值时,直接new了一个工厂类。工厂类中private一个final的GlobalComponent,也就是我们之前传入.globalComponent(new MyApplication().get())传入的Component。并重写了Global的get()方法,返回globalComponent.global()。
回顾一下,这个方法在哪:
@Singleton @Component(modules = GlobalModule.class) public interface GlobalComponent { Global global(); }
之前我们传入Component就是为了通过实例好的Component来调用其中的构造函数。
一切都串起来了。
为什么会有全局单例?
因为不同Activity依赖注入时调用的Component是同一个,Component里面的方法还是@Singleton局部单例模式。所以注入的依赖也是同一个。
好好品一下这个问题。
让你的头发休息一下,然后接着看后面的。
后面接着一个比较简单的进阶组件:@Qualifier
和前面讲到的@Scope一样,也需要实现后在调用,默认实现有@Named。看看源码:
@Qualifier @Documented @Retention(RUNTIME) public @interface Named { /** The name. */ String value() default ""; }
之前我们讲过Module中不能有相同返回类型的函数,但是如果我们有需要注入同一个类却要用不同的构造函数注入呢?
就要用到函数命名了。两边标记就行,一边是Module中:
@Named("null") @Provides Coffee provideCoffee(){ return new Coffee(); } @Named("lanshan") @Provides Coffee provideCoffee1(){ return new Coffee("蓝山"); }
另一边就是Activity中:
@Inject @Named("lanshan") Coffee coffee1; @Inject @Named("null") Coffee coffee2;
如果自定义也很简单,和前面的一样,举两个栗子:
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface MyNamed1 {
}
@Qualifier @Documented @Retention(RUNTIME) public @interface MyNamed2 { }
因为没有写方法体,那就得一个函数实例化一个@Qualifier,远不如直接用@Named来的简单。
@Inject
@MyNamed1
Coffee coffee1;
@Inject
@MyNamed2
Coffee coffee2;
这个我就不多讲了,相信大家都能看的一目了然。
到此Dagger2的学习可以告一段落。剩下的疑难点需要在使用中慢慢发掘。
(实际上我是过了五个月才发现还有篇草稿,忘了怎么往下写,直接结尾吧!)