前言
上篇文章我們介紹了dagger2.android的如何使用,知其然知其所以然疯趟,本篇我們一起來(lái)看下艺智,dagger2.android是怎么在dagger2基礎(chǔ)上實(shí)現(xiàn)注入的。
注意
- 本篇不講代碼生成過(guò)程汰翠,后續(xù)文章介紹。
- 本篇講解dagger2.android注入原理肯定還是dagger2注入原理昭雌,所以請(qǐng)先閱讀前3篇文章复唤,了解Provider、Builder 烛卧、SubcomponentImpl佛纫、MembersInjector等主要類作用。
dagger2和dagger2.android 調(diào)用注入的區(qū)別
調(diào)用區(qū)別我們上篇文章已經(jīng)詳細(xì)講到总放,本篇從調(diào)用區(qū)別引入原理實(shí)現(xiàn)呈宇。dagger2中acitivity實(shí)現(xiàn)注入代碼如下:
private void initInjector() {
mComponent = getAppComponent()
.mainActivityComponent()
.activity(this)
.build();
}
dagger2.anodriod中acitivity實(shí)現(xiàn)注入代碼如下:
Application的改造代碼:
public class MyApplication extends Application implements HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
@Override
public void onCreate() {
super.onCreate();
DaggerMyAppComponent.create().inject(this);
}
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
}
activity的注入代碼
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
區(qū)別為:
dagger2.android的調(diào)要先改造了Application,activity里不需要再調(diào)用具體的component接口方法局雄。
代碼雖有區(qū)別,完成任務(wù)是一樣的甥啄。完成:
拿到MainActivityComponent的的實(shí)現(xiàn)類,然后實(shí)現(xiàn)MainActivity的注入炬搭。
我們本篇就是要講解dagger2.android是怎么完成這個(gè)過(guò)程的蜈漓,從代碼上看就是,DaggerMyAppComponent.create().inject(this)和 AndroidInjection.inject(this)做了什么宫盔。還是以MainActivity注入為例融虽。
dagger2.android 注入原理
DaggerMyAppComponent.create().inject(this)
先給出這行代碼作用的結(jié)論:
將MainActivityComponent等subComponent的實(shí)現(xiàn)類的工廠實(shí)例緩存(簡(jiǎn)單理解方式,實(shí)際緩存是工廠實(shí)例進(jìn)一步封裝)起來(lái)灼芭,activity注入時(shí)候備用衣形。
兩個(gè)問(wèn)題:
- 緩存在哪?
緩存在Application的dispatchingAndroidInjector中姿鸿。 - 如何緩存?
也是通過(guò)注入方式緩存倒源。
帶著結(jié)論我們開始擼代碼苛预,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實(shí)例。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
//待會(huì)要回調(diào)此處笋熬,請(qǐng)注意
get() {
return new MainActivitySubcomponentBuilder();
}
};
this.secondActivitySubcomponentBuilderProvider =
......
}
實(shí)例化了mainActivitySubcomponentBuilderProvider 热某、secondActivitySubcomponentBuilderProvider 等SubcomponentBuilderProvider ,這里Provider細(xì)節(jié)不再深入,簡(jiǎn)單理解為Subcomponent實(shí)現(xiàn)類的工廠類昔馋。這里完成了Subcomponent實(shí)現(xiàn)類的工廠類的實(shí)例化筹吐,接下來(lái)就是把他緩存起來(lái)了。
inject()方法源碼:
@Override
public void inject(MyApplication application) {
injectMyApplication(application);
}
private MyApplication injectMyApplication(MyApplication instance) {
MyApplication_MembersInjector.injectDispatchingAndroidInjector(
instance, getDispatchingAndroidInjectorOfActivity());
return instance;
}
}
代碼調(diào)用到了MyApplication_MembersInjector的injectDispatchingAndroidInjector方法秘遏,第二個(gè)參數(shù)getDispatchingAndroidInjectorOfActivity()方法返回的是對(duì)上面我初始化的Provider進(jìn)一步封裝后的結(jié)果丘薛。在dagger2中MembersInjector是真正完成注入的地方,我們看進(jìn)去為MyApplication注入了什么邦危。
public static void injectDispatchingAndroidInjector(
MyApplication instance, DispatchingAndroidInjector<Activity> dispatchingAndroidInjector) {
instance.dispatchingAndroidInjector = dispatchingAndroidInjector;
}
到這里洋侨,真正的我們之前說(shuō)的:用注入的方式把subComponent的實(shí)現(xiàn)類的工廠實(shí)例緩存在Application的dispatchingAndroidInjector中。
AndroidInjection.inject(this)
這行代碼完成的工作是:
從Application的dispatchingAndroidInjector中獲取MainActivityComponent的的實(shí)現(xiàn)類實(shí)例倦蚪,然后完成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<Activity> activityInjector =
((HasActivityInjector) application).activityInjector();
checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
activityInjector.inject(activity);
}
代碼解釋:異常處理,然后得到application的dispatchingAndroidInjector陵且,調(diào)用其inject(activity)方法裁僧。
繼續(xù)看到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<AndroidInjector.Factory<? extends T>> factoryProvider =
injectorFactories.get(instance.getClass());
if (factoryProvider == null) {
return false;
}
@SuppressWarnings("unchecked")
AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
try {
AndroidInjector<T> 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);
}
}
代碼又調(diào)用到maybeInject方法,還是以MainActivity為例慕购,
- 獲得MainActivity對(duì)應(yīng)我們之前緩存的Provider
- 調(diào)用get方法獲得MainActivitySubcomponentBuilder實(shí)例factory(參考上面provider實(shí)例化的地方get的具體實(shí)現(xiàn))
- 調(diào)用MainActivitySubcomponentBuilder的create方法聊疲,create方法中又調(diào)用到build方法:
@Override
public AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent build() {
if (seedInstance == null) {
throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
}
return new MainActivitySubcomponentImpl(this);
}
}
最終我終于得到了MainActivitySubcomponent的實(shí)現(xiàn)類MainActivitySubcomponentImpl,回到上面主流程中脓钾,調(diào)用了其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;
}
}
到這里終于調(diào)用了各種MembersInjector完成了MainActivity的注入售睹。
最后一句話總結(jié)dagger2.android的注入原理:
將MainActivityComponent的實(shí)現(xiàn)類的工廠實(shí)例(簡(jiǎn)單理解)緩存起來(lái),MainActivity注入時(shí)取出工廠實(shí)例可训,build構(gòu)建得到MainActivitySubcomponentImpl后昌妹,完成MainActivity注入。