讀懂 Dagger2 源碼

理解 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);
    }
}

需要做兩件事

  1. 將 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;
        }

    }
}

  1. 調(diào)用 builder 方法時(shí),會(huì)返回一個(gè)內(nèi)部靜態(tài)類 Builder 的實(shí)例
public static Builder builder(){
    return new Builder();
}
  1. 內(nèi)部靜態(tài)類 Builder ,這是一般構(gòu)建者的模式的 Builder,然后調(diào)用 Builder 類的 build 方法看代碼會(huì)給我們返回一個(gè) AppComponent 然后我們看代碼 build

    1. 先創(chuàng)建了一個(gè) AppModule
    2. 然后將 Builder 自己作為參數(shù)傳入給 AppComponent 構(gòu)造函數(shù)創(chuàng)建一個(gè) AppComponent 實(shí)例。
  2. 在 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)也是一套

  1. create 創(chuàng)建自己然后 module 傳入
  2. module 作為 AppModule_ProvideManagerFactory 參數(shù)在構(gòu)造賦值
  3. 調(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容