理解 Dagger2 的源碼
Dagger2 幫助我們將被注入類自動(dòng)地注入到目標(biāo)類,有利解耦,從而讓維護(hù)項(xiàng)目的依賴關(guān)系變得輕松。
通過(guò)代碼實(shí)現(xiàn)一下 dagger 是如何實(shí)現(xiàn)依賴注入,我們創(chuàng)建一個(gè)類 DataManager 用作被注入的類。
public class DataManager {
private static final String TAG = "DataManager";
public DataManager() {
Log.d(TAG, "DataManager: ininial");
}
}
然后我們需要 DataManager 注入到目標(biāo)中 MainActivity,因?yàn)?MainActivity 并不是由我們開(kāi)發(fā)人員直接創(chuàng)建的,是由系統(tǒng)創(chuàng)建,所以我們需要將一些依賴以屬性的形式進(jìn)行注入
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
好我們就開(kāi)始來(lái)實(shí)現(xiàn),要進(jìn)行注入,如果熟悉 dagger 知道我們需要一個(gè) module 類和一個(gè) component 接口
首先 Module 負(fù)責(zé)提供要注入的類的對(duì)象,在 Dagger 中我們需要 @Module 來(lái)修飾為了是 apt 能夠識(shí)別到這個(gè)類進(jìn)行代碼生成工作。
public class AppModule {
public DataManager provideManager(){
return new DataManager();
}
}
然后 Component 負(fù)責(zé)將被注入類注入到目標(biāo)類中,在 Dagger 中我們需要注解 @Component 以及將 @Component 以及已經(jīng)定義依賴的 module
public interface AppComponent {
void inject(MainActivity activity);
}
最后我們還需要 MainActivity 中做一些事
public class MainActivity extends AppCompatActivity {
public DataManager dataManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ScAppComponent.builder()
.appMoudle(new AppModule())
.build() //使用構(gòu)建者模式創(chuàng)建一個(gè) Component 實(shí)例
.inject(this);
}
}
需要做兩件事
- 將 DataManager 作為屬性,需要是 public 類型
在編譯過(guò)程會(huì)用到 apt 技術(shù)生成一些類用來(lái)實(shí)現(xiàn),這里我們就手動(dòng)寫(xiě)這些類
通常使用時(shí)我們通常會(huì)以這種形式來(lái)實(shí)現(xiàn),
DaggerAppComponent
.builder()
.appModule(new AppModule())
.build()
.inject(this)
appModule 應(yīng)該代碼生成時(shí)根據(jù) AppModule 生成方法,通過(guò) builder 可看出來(lái)這里使用構(gòu)建者的設(shè)計(jì)模式。我們這里手動(dòng)地完成代碼生成以便了解 dagger 是如何將類 DataManager 注入到 MainActivity
我們先寫(xiě) ScAppComponent 這個(gè)自動(dòng)生成的類,在 Dagger 命名應(yīng)該為 DaggerAppComponent,這里我用我習(xí)慣的 Sc 開(kāi)頭以便區(qū)別,這里 ScAppComponent 實(shí)現(xiàn)之前定義好的 AppComponent 接口,實(shí)現(xiàn) inject 方法,這個(gè)方法指定要將 DataManager 注入的位置。
public class ScAppComponent implements AppComponent{
private Provider<DataManager> provideManagerProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
public ScAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
private void initialize(final Builder builder){
this.provideManagerProvider = (Provider<DataManager>) AppModule_ProvideManagerFactory.create(builder.appModule);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(provideManagerProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static Builder builder(){
return new Builder();
}
public static AppComponent create(){
return builder().build();
}
public static final class Builder{
private AppModule appModule;
private Builder(){}
public AppComponent build(){
if(appModule == null){
this.appModule = new AppModule();
}
return new ScAppComponent(this);
}
public Builder appMoudle(AppModule appModule){
// this.appModule = Preconditions.checkNotNull(appModule)
return this;
}
}
}
- 調(diào)用 builder 方法時(shí),會(huì)返回一個(gè)內(nèi)部靜態(tài)類 Builder 的實(shí)例
public static Builder builder(){
return new Builder();
}
-
內(nèi)部靜態(tài)類 Builder ,這是一般構(gòu)建者的模式的 Builder,然后調(diào)用 Builder 類的 build 方法看代碼會(huì)給我們返回一個(gè) AppComponent 然后我們看代碼 build
- 先創(chuàng)建了一個(gè) AppModule
- 然后將 Builder 自己作為參數(shù)傳入給 AppComponent 構(gòu)造函數(shù)創(chuàng)建一個(gè) AppComponent 實(shí)例。
-
在 AppComponent 構(gòu)造函數(shù)中會(huì)調(diào)用 initialize 方法
private void initialize(final Builder builder){ this.provideManagerProvider = (Provider<DataManager>) AppModule_ProvideManagerFactory.create(builder.appModule); this.mainActivityMembersInjector = MainActivity_MembersInjector.create(provideManagerProvider); }
在 initialize 方法中,會(huì)初始化
private Provider<DataManager> provideManagerProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
這里我們?cè)诜謩e看一下這兩個(gè) AppModule_ProvideManagerFactory 和 MainActivity_MembersInjector 他們倆也是通過(guò) APT 生成,所以我們一步一步寫(xiě)一寫(xiě),來(lái)了解他們都做了什么,先看 AppModule_ProvideManagerFactory ,看名字應(yīng)該是一個(gè)工廠類,用于生成 DataManager 實(shí)例的吧。
public final class AppModule_ProvideManagerFactory implements Factory<DataManager> {
private final AppModule module;
public AppModule_ProvideManagerFactory(AppModule module) {
assert module != null;
this.module = module;
}
@Override
public DataManager get() {
return module.provideManager();
}
public static Factory<DataManager> create(AppModule module){
return new AppModule_ProvideManagerFactory(module);
}
}
我們從 create 入手,這里返回一個(gè) Factory<DataManager> 類型的對(duì)象那么我們就簡(jiǎn)單定義一下。Factory<T> 作為一個(gè)接口擴(kuò)展了 Provider<T>接口
public interface Factory<T> extends Provider<T>{
}
所以定義一下Provider<T> 有一個(gè)方法 get 用于返回我們創(chuàng)建好的(要注入的)實(shí)例
public interface Provider<T> {
T get();
}
好準(zhǔn)備好了所需的接口,我們?cè)倩氐?AppModule_ProvideManagerFactory 這需要實(shí)現(xiàn) Factory<T> 接口,用于提供產(chǎn)品的工廠吧
這里的 get 方法中是調(diào)用我們 module(AppModule)的 provideManager 方法來(lái)返回 DataManager 那么我們就需要有一個(gè) AppModule 的實(shí)例,實(shí)現(xiàn)起來(lái)也是一套
- create 創(chuàng)建自己然后 module 傳入
- module 作為 AppModule_ProvideManagerFactory 參數(shù)在構(gòu)造賦值
- 調(diào)用 get 實(shí)際就是調(diào)用 AppModule.provideManager
然后再看 MainActivity_MembersInjector 這個(gè)類,需要實(shí)現(xiàn) MembersInjector<T> 接口
public interface MembersInjector<T> {
void injectMembers(T t);
}
public class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<DataManager> dataManagerProvider;
public MainActivity_MembersInjector(Provider<DataManager> dataManagerProvider) {
assert dataManagerProvider != null;
this.dataManagerProvider = dataManagerProvider;
}
public static MembersInjector<MainActivity> create(Provider<DataManager> dataManagerProvider){
return new MainActivity_MembersInjector(dataManagerProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if(instance == null){
throw new NullPointerException("空指針");
}
instance.dataManager = dataManagerProvider.get();
}
public static void injectDataManager(
MainActivity instance, Provider<DataManager> dataManagerProvider
){
instance.dataManager = dataManagerProvider.get();
}
}
這里 create 需要傳入 Provider<DataManager> 的 dataManagerProvider 提供 DataManger ,調(diào)用 dataManagerProvider.get 方法就可以得到 DataManager 的實(shí)例讓然后在 injectDataManager 方法中將這個(gè)實(shí)例賦值給 MainActivity的dataManager 屬性來(lái)完成注入。所以這個(gè)類需要一個(gè) Provider<DataManager> 實(shí)例這是在構(gòu)造函數(shù)傳入的 create 的方式與上面的 AppModule_ProvideManagerFactory 的 create 套路相同,injectMembers(MainActivity instance) 是將 MainActivity 導(dǎo)入進(jìn)入,然后我們就可以輕松地將 provider 提供 DataManager 實(shí)例賦給 MainActivity 的屬性。
3. 這里調(diào)用 inject方法是 ScAppComponent的 inject 方法 也就是
mainActivityMembersInjector 的 injectMembers 方法來(lái)將 MainActivity 傳入到類供注入
ScAppComponent.builder()
.appMoudle(new AppModule())
.build() //使用構(gòu)建者模式創(chuàng)建一個(gè) Component 實(shí)例
.inject(this);
運(yùn)行代碼
: DataManager: ininial