本系列所有文章:
Android 神兵利器Dagger2使用詳解(一)基礎(chǔ)使用
Android 神兵利器Dagger2使用詳解(二)Module&Component源碼分析
Android 神兵利器Dagger2使用詳解(三)MVP架構(gòu)下的使用
Android 神兵利器Dagger2使用詳解(四)Scope注解的使用及源碼分析
告別Dagger2模板代碼:DaggerAndroid使用詳解
告別Dagger2模板代碼:DaggerAndroid原理解析
該系列首發(fā)于我的CSDN專欄 :
Android開發(fā):Dagger2詳解
概述
距離我的上一篇文章發(fā)布以來,有幸收獲了一些朋友的認可,我很開心。
在上一篇文章中,我簡單敘述了Dagger2這個庫目前在Android開發(fā)中的一些短板,為什么我們學習Dagger-Android這個拓展庫,以及如何使用這個拓展庫。
今天我們進行代碼分析,看看Dagger-Android是如何基于Dagger2實現(xiàn)一行代碼實現(xiàn)所有同類組件依賴注入的。
閱讀本文也許您需要準備的
- 本文可能需要您對Dagger2有一定的了解,包括它內(nèi)部模板代碼生成的一些邏輯。
核心代碼
書承上文,我們知道,我們實現(xiàn)依賴注入的代碼主要為以下兩行:
public class MyApplication extends Application implements HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
@Override
public void onCreate() {
super.onCreate();
//1.Application級的依賴注入
DaggerMyAppComponent.create().inject(this);
}
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
}
public class BaseActivity extends AppCompatActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//2.Activity級的依賴注入
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
}
拋開這兩行,也許我們還有更多疑問:
- 1.MyApplication中的dispatchingAndroidInjector成員是干嘛的
- 2.MyApplication實現(xiàn)的HasActivityInjector接口和實現(xiàn)的activityInjector()方法又是干嘛的
- 3.為什么這樣2行依賴注入代碼,就能代替之前我們每個Activity都需要寫的模板代碼呢:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DO THIS FIRST. Otherwise frombulator might be null!
((SomeApplicationBaseType) getContext().getApplicationContext())
.getApplicationComponent()
.newActivityComponentBuilder()
.activity(this)
.build()
.inject(this);
// ... now you can write the exciting code
}
直接公布結(jié)論:
這三張圖描述了很多東西,我們不需要先去看懂它,我們會隨著我們的步驟,一步步分析透徹它,撥開云霧見晴天。、
首先我們分析Application中的這行代碼:
DaggerMyAppComponent.create().inject(this);
一、DaggerMyAppComponent.create()原理
我們先點開create()方法,可以看到,無非是初始化了一個DaggerMyAppComponent對象,然后執(zhí)行了initialize()方法
public static MyAppComponent create() {
return new Builder().build();
}
public static final class Builder {
private Builder() {
}
public MyAppComponent build() {
return new DaggerMyAppComponent(this);
}
}
private DaggerMyAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
我們接著看initialize()方法:
private void initialize(final Builder builder) {
//1
this.mainActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder>() {
@Override
public AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder
get() {
return new MainActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider = (Provider) mainActivitySubcomponentBuilderProvider;
this.secondActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder>() {
@Override
public AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder
get() {
return new SecondActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider2 = (Provider) secondActivitySubcomponentBuilderProvider;
//2
this.mapOfClassOfAndProviderOfFactoryOfProvider =
MapProviderFactory
.<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>>builder(2)
.put(MainActivity.class, bindAndroidInjectorFactoryProvider)
.put(SecondActivity.class, bindAndroidInjectorFactoryProvider2)
.build();
//3
this.dispatchingAndroidInjectorProvider =
DispatchingAndroidInjector_Factory.create(mapOfClassOfAndProviderOfFactoryOfProvider);
//4
this.myApplicationMembersInjector =
MyApplication_MembersInjector.create(dispatchingAndroidInjectorProvider);
}
這就有點難受了,代碼很多,我們一步步慢慢分析。
我們不要一次想著把這些代碼徹底讀懂,我們首先大概對整個流程有個了解,之后慢慢拆分代碼不遲:
- 我們可以理解為直接初始化了MainActivitySubcomponentBuilder和SecondActivitySubcomponentBuilder的對象,這個對象能夠提供一個對應ActivityComponent的實例化對象,有了這個實例化對象,我們就能夠?qū)腁ctivity進行依賴注入。
- 這個很明顯了,把所有ActivityComponent的實例化對象都存儲到一個Map中,然后這個Map通過放入mapOfClassOfAndProviderOfFactoryOfProvider對象中。
- 通過mapOfClassOfAndProviderOfFactoryOfProvider初始化dispatchingAndroidInjectorProvider對象
- 通過dispatchingAndroidInjectorProvider對象初始化myApplicationMembersInjector對象
好的基本差不多了 我們看看每個步驟都是如何實現(xiàn)的
第1步詳細分析
以SecondActivity的這行代碼為例:
this.secondActivitySubcomponentBuilderProvider =
new dagger.internal.Factory< //1.看這行,實際上是new了一個能提供SecondActivitySubcomponentBuilder()的Provider
AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder>() {
@Override
public AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder
get() {
//2.這個SecondActivitySubcomponentBuilder能干什么呢
return new SecondActivitySubcomponentBuilder();
}
};
private final class SecondActivitySubcomponentImpl
implements AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent {
private MembersInjector<SecondActivity> secondActivityMembersInjector;
//3.我們點開構(gòu)造方法,看到實際是走了initialize(builder);
private SecondActivitySubcomponentImpl(SecondActivitySubcomponentBuilder builder) {
assert builder != null;
initialize(builder);
}
@SuppressWarnings("unchecked")
private void initialize(final SecondActivitySubcomponentBuilder builder) {
//4.實際上是初始化了一個SecondActivity_MembersInjector,這個Injector能夠?qū)econdActivity所需要的對象提供注入
this.secondActivityMembersInjector =
SecondActivity_MembersInjector.create(SecondActivityModule_ProvideNameFactory.create());
}
@Override
public void inject(SecondActivity arg0) {
//5.我們不難想象,不久后當SecondActivity需要依賴注入,一定會執(zhí)行這行代碼進行對象注入
secondActivityMembersInjector.injectMembers(arg0);
}
}
看到這里我們明白了,實際上第一步是ApplicationComponent實例化了所有的ActivityComponent(就是那個能提供SecondActivitySubcomponentBuilder()的Provider)
然后每個ActivityComponent都能提供某個Activity依賴注入所需要的ActivityMembersInjector。
第2步第3步分析
第2步就很簡單了,這些ActivityComponent都被放入了一個Map集合中,該集合又放入了apOfClassOfAndProviderOfFactoryOfProvider中,這個Provider實際上也是一個工廠,負責提供該Map的實例化
第3步也很好理解,我們MapProvider工廠交給了就是dispatchingAndroidInjectorProvider去管理。
第4步分析:
實際上我們傳入dispatchingAndroidInjectorProvider做了什么呢?
我們看看MyApplication_MembersInjector對象是干嘛的:
//核心代碼
public final class MyApplication_MembersInjector implements MembersInjector<MyApplication> {
private final Provider<DispatchingAndroidInjector<Activity>> dispatchingAndroidInjectorProvider;
...
...
...
//依賴注入Application!
@Override
public void injectMembers(MyApplication instance) {
instance.dispatchingAndroidInjector = dispatchingAndroidInjectorProvider.get();
}
}
大家可以明白了,原來第四步初始化該對象時,會將傳入的dispatchingAndroidInjectorProvider存儲起來,將來用到的時候?qū)⑵鋵ο笞⑷氲叫枰⑷氲腁pplication中:
public class MyApplication extends Application implements HasActivityInjector {
//就是注入給這個成員變量!
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
//省略其他代碼
...
...
}
整理思路
現(xiàn)在我們再來看一下這張圖,相信您已經(jīng)對這張圖有所領(lǐng)會了。
可以看到,Application進行初始化時,僅僅一部DaggerMyAppComponent.create(),就已經(jīng)處理了如此多的事件,初始化了這么多工廠類,等待我們?nèi)フ{(diào)用他們實現(xiàn)依賴注入了。
二、DaggerMyAppComponent.create().inject(this)原理
其實這個步驟就是確定一下我們上面的對Dagger-Android這個庫的分析是否是對的,我們來看這行代碼
public final class DaggerMyAppComponent implements MyAppComponent {
...
...
...
@Override
public void inject(MyApplication application) {
myApplicationMembersInjector.injectMembers(application);
}
}
這就和我們上面第四步的分析吻合了:
//我們剛才分析過的,再看一遍
//核心代碼
public final class MyApplication_MembersInjector implements MembersInjector<MyApplication> {
private final Provider<DispatchingAndroidInjector<Activity>> dispatchingAndroidInjectorProvider;
...
...
...
//依賴注入Application!
@Override
public void injectMembers(MyApplication instance) {
instance.dispatchingAndroidInjector = dispatchingAndroidInjectorProvider.get();
}
}
public class MyApplication extends Application implements HasActivityInjector {
//就是注入給這個成員變量!
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
//省略其他代碼
...
...
}
整理思路
可以看到,這一步實際上我們做了至關(guān)重要的一步,就是把Application中的這個不知道是干什么的成員變量進行了初始化!!!
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
我們現(xiàn)在知道,這個dispatchingAndroidInjector中,實際擁有一個Map,Map中有著所有Activity所需依賴注入使用的Component!
可以說,這個看起來平凡無奇的成員變量,才是我們整個項目依賴注入的大管家!
頓悟
相信如果您認真一步步看到這里,對于下面的2個問題,您已經(jīng)有了自己的答案:
- 1.MyApplication中的dispatchingAndroidInjector成員是干嘛的
三、 AndroidInjection.inject(this)原理
我們在初始化一個Activity,必然會調(diào)用BaseActivity中的這行代碼:
AndroidInjection.inject(this)
我們好奇,為什么僅僅在BaseActivity這樣1行依賴注入代碼,就能代替之前我們每個Activity都需要寫的模板代碼呢?
答案近在眼前。
public final class AndroidInjection {
...
...
...
public static void inject(Activity activity) {
//核心代碼如下
//1.獲取Application
Application application = activity.getApplication();
//2.通過activityInjector()獲取dispatchingAndroidInjector對象!
AndroidInjector<Activity> activityInjector =
((HasActivityInjector) application).activityInjector();
//3.dispatchingAndroidInjector依賴注入
activityInjector.inject(activity);
}
}
前兩步毫無技術(shù)含量,我們繼續(xù)看activityInjector.inject(activity):
我們需要找到真正的activityInjector對象,就是DispatchingAndroidInjector:
public final class DispatchingAndroidInjector<T> implements AndroidInjector<T> {
@Override
public void inject(T instance) { //instance在這里為Activity
//1.執(zhí)行maybeInject()方法
boolean wasInjected = maybeInject(instance);
}
public boolean maybeInject(T instance) { //instance在這里為Activity
//2.獲取對應Provider
Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
injectorFactories.get(instance.getClass());
AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
//3.獲取對應的ActivityMembersInjector
AndroidInjector<T> injector =
factory.getClass().getCanonicalName());
//4.注入到對應的Activity中
injector.inject(instance);
}
}
整理思路
可以看到,這一步實際上我們只是取得Application中的大管家dispatchingAndroidInjector,通過它取得了對應Activity的Inject實例,并進行依賴注入。
頓悟
相信如果您認真一步步看到這里,對于下面的2個問題,您已經(jīng)有了自己的答案:
- 2.MyApplication實現(xiàn)的HasActivityInjector接口和實現(xiàn)的activityInjector()方法又是干嘛的
- 3.為什么這樣2行依賴注入代碼,就能代替之前我們每個Activity都需要寫的模板代碼呢:
至此,AndroidInject原理分析基本也到了尾聲
附錄
最后提供一下本文demo源碼連接和圖片資源,都已放到Github: