前言

上篇文章我们介绍了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",

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注入。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐