前言
上篇文章我们介绍了dagger2.android的如何使用,知其然知其所以然,本篇我们一起来看下,dagger2.android是怎么在dagger2基础上实现注入的。
注意
- 本篇不讲代码生成过程,后续文章介绍。
- 本篇讲解dagger2.android注入原理肯定还是dagger2注入原理,所以请先阅读前3篇文章,了解Provider、Builder 、SubcomponentImpl、MembersInjector等主要类作用。
dagger2和dagger2.android 调用注入的区别
调用区别我们上篇文章已经详细讲到,本篇从调用区别引入原理实现。dagger2中acitivity实现注入代码如下:
private void initInjector() {
mComponent = getAppComponent()
.mainActivityComponent()
.activity(this)
.build();
}
dagger2.anodriod中acitivity实现注入代码如下:
Application的改造代码:
public class MyApplication extends Application implements HasActivityInjector {
@Inject
DispatchingAndroidInjector dispatchingAndroidInjector;
@Override
public void onCreate() {
super.onCreate();
DaggerMyAppComponent.create().inject(this);
}
@Override
public AndroidInjector activityInjector() {
return dispatchingAndroidInjector;
}
}
activity的注入代码
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
区别为:
dagger2.android的调要先改造了Application,activity里不需要再调用具体的component接口方法。
代码虽有区别,完成任务是一样的。完成:
拿到MainActivityComponent的的实现类,然后实现MainActivity的注入。
我们本篇就是要讲解dagger2.android是怎么完成这个过程的,从代码上看就是,DaggerMyAppComponent.create().inject(this)和 AndroidInjection.inject(this)做了什么。还是以MainActivity注入为例。
dagger2.android 注入原理
DaggerMyAppComponent.create().inject(this)
先给出这行代码作用的结论:
将MainActivityComponent等subComponent的实现类的工厂实例缓存(简单理解方式,实际缓存是工厂实例进一步封装)起来,activity注入时候备用。
两个问题:
- 缓存在哪?
缓存在Application的dispatchingAndroidInjector中。 - 如何缓存?
也是通过注入方式缓存。
带着结论我们开始撸代码,DaggerMyAppComponent.create()方法:
public static MyAppComponent create() {
return new Builder().build();
}
public static final class Builder {
private Builder() {}
public MyAppComponent build() {
return new DaggerMyAppComponent(this);
}
}
就是返回了DaggerMyAppComponent实例。DaggerMyAppComponent初始化又做了什么:
private DaggerMyAppComponent(Builder builder) {
initialize(builder);
}
private void initialize(final Builder builder) {
this.mainActivitySubcomponentBuilderProvider =
new Provider<
AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder>() {
@Override
public AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder
//待会要回调此处,请注意
get() {
return new MainActivitySubcomponentBuilder();
}
};
this.secondActivitySubcomponentBuilderProvider =
......
}
实例化了mainActivitySubcomponentBuilderProvider 、secondActivitySubcomponentBuilderProvider 等SubcomponentBuilderProvider ,这里Provider细节不再深入,简单理解为Subcomponent实现类的工厂类。这里完成了Subcomponent实现类的工厂类的实例化,接下来就是把他缓存起来了。
inject()方法源码:
@Override
public void inject(MyApplication application) {
injectMyApplication(application);
}
private MyApplication injectMyApplication(MyApplication instance) {
MyApplication_MembersInjector.injectDispatchingAndroidInjector(
instance, getDispatchingAndroidInjectorOfActivity());
return instance;
}
}
代码调用到了MyApplication_MembersInjector的injectDispatchingAndroidInjector方法,第二个参数getDispatchingAndroidInjectorOfActivity()方法返回的是对上面我初始化的Provider进一步封装后的结果。在dagger2中MembersInjector是真正完成注入的地方,我们看进去为MyApplication注入了什么。
public static void injectDispatchingAndroidInjector(
MyApplication instance, DispatchingAndroidInjector dispatchingAndroidInjector) {
instance.dispatchingAndroidInjector = dispatchingAndroidInjector;
}
到这里,真正的我们之前说的:用注入的方式把subComponent的实现类的工厂实例缓存在Application的dispatchingAndroidInjector中。
AndroidInjection.inject(this)
这行代码完成的工作是:
从Application的dispatchingAndroidInjector中获取MainActivityComponent的的实现类实例,然后完成MainActivity的注入。
public static void inject(Activity activity) {
checkNotNull(activity, "activity");
Application application = activity.getApplication();
if (!(application instanceof HasActivityInjector)) {
throw new RuntimeException(
String.format(
"%s does not implement %s",
application.getClass().getCanonicalName(),
HasActivityInjector.class.getCanonicalName()));
}
AndroidInjector activityInjector =
((HasActivityInjector) application).activityInjector();
checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
activityInjector.inject(activity);
}
代码解释:异常处理,然后得到application的dispatchingAndroidInjector,调用其inject(activity)方法。
继续看到DispatchingAndroidInjector中inject方法:
@Override
public void inject(T instance) {
boolean wasInjected = maybeInject(instance);
if (!wasInjected) {
throw new IllegalArgumentException(errorMessageSuggestions(instance));
}
}
public boolean maybeInject(T instance) {
Provider> factoryProvider =
injectorFactories.get(instance.getClass());
if (factoryProvider == null) {
return false;
}
@SuppressWarnings("unchecked")
AndroidInjector.Factory factory = (AndroidInjector.Factory) factoryProvider.get();
try {
AndroidInjector injector =
checkNotNull(
factory.create(instance), "%s.create(I) should not return null.", factory.getClass());
injector.inject(instance);
return true;
} catch (ClassCastException e) {
throw new InvalidInjectorBindingException(
String.format(
"%s does not implement AndroidInjector.Factory<%s>",
factory.getClass().getCanonicalName(), instance.getClass().getCanonicalName()),
e);
}
}
代码又调用到maybeInject方法,还是以MainActivity为例,
- 获得MainActivity对应我们之前缓存的Provider
- 调用get方法获得MainActivitySubcomponentBuilder实例factory(参考上面provider实例化的地方get的具体实现)
- 调用MainActivitySubcomponentBuilder的create方法,create方法中又调用到build方法:
@Override
public AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent build() {
if (seedInstance == null) {
throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
}
return new MainActivitySubcomponentImpl(this);
}
}
最终我终于得到了MainActivitySubcomponent的实现类MainActivitySubcomponentImpl,回到上面主流程中,调用了其inject方法:
@Override
public void inject(MainActivity arg0) {
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectClassName(
instance, MainActivityModule_ProvideNameFactory.proxyProvideName());
MainActivity_MembersInjector.injectSp(instance, getSharedPreferences());
MainActivity_MembersInjector.injectPresenter(instance, getMainPresenter());
MainActivity_MembersInjector.injectS1(instance, provideStudentProvider.get());
MainActivity_MembersInjector.injectS2(instance, provideStudentProvider.get());
return instance;
}
}
到这里终于调用了各种MembersInjector完成了MainActivity的注入。
最后一句话总结dagger2.android的注入原理:
将MainActivityComponent的实现类的工厂实例(简单理解)缓存起来,MainActivity注入时取出工厂实例,build构建得到MainActivitySubcomponentImpl后,完成MainActivity注入。