天天看點

Android MVP+Retrofit+dagger2+RxAndroid架構整合(7)----Dagger2篇

作者:hwj3747

轉載請注明

目錄

  • (1)配置篇
  • (2)Lambda表達式
  • (3)icepick篇
  • (4)butterknife篇
  • (5)MVP篇
  • (6)Retrofit篇
  • (7)Dagger2篇
  • (8)RxAndroid/RxJava篇

什麼是dagger2

Dagger是為Android和Java平台提供的一個完全靜态的,在編譯時進行依賴注入的架構,原來是由Square公司維護,現在由Google維護。一句話,dagger2其實就是一套依賴注入架構。那麼什麼是依賴注入呢?

具體含義是:當某個角色(可能是一個Java執行個體,調用者)需要另一個角色(另一個Java執行個體,被調用者)的協助時,在 傳統的程式設計過程中,通常由調用者來建立被調用者的執行個體。但在dagger2裡,建立被調用者的工作不再由調用者來完成,而是由dagger2來完成,然後注入調用者,是以也稱為依賴注入。

為什麼需要dagger2

說實話,剛接觸dagger2的時候我也是一臉懵逼,這個東西這麼繁瑣,為什麼要用它呢?這個問題其實就是為何我們需要依賴注入。有本書上這樣寫道:依賴注入不是目的,它是一系列工具和手段,最終的目的是幫助我們開發出松散耦合、可維護、可測試的代碼和程式。可想而知,其最終目的是實作解耦。何為解耦?怎麼解耦?舉個例子說明一下:

前面我們講到MVP架構,我們的Presenter層構造函數可能需要一些參數:通路服務端的AbsService執行個體,做網絡請求線程切換的SchedulerProvider ,如下,

public class TestPresenter extends BasePresenter<TestView> {
    AbsService mAbsService;
    SchedulerProvider mSchedulerProvider;

    public TestPresenter(AbsService absService,SchedulerProvider schedulerProvider) {
        this.mAbsService=absService;
        this.mSchedulerProvider=schedulerProvider;
    }
}
           

那麼我們在執行個體化這個Presenter的時候就需要這樣做:

AbsService mAbsService=AbsService.getInstance();
        SchedulerProvider schedulerProvider=SchedulerProvider.DEFAULT;
        TestPresenter testPresenter=new TestPresenter(mAbsService,schedulerProvider);
           

需要把TestPresenter需要的參數一個個的執行個體化,然後作為參數傳給它。試想一下,如果我們的AbsService和SchedulerProvider 還需要很多參數,或者TestPresenter需要3個乃至更多的參數,那我們執行個體化一個TestPresenter要做的操作是不是太多了,這樣實在是太誇張了,我們隻是需要一個TestPresenter執行個體而已,就必須知道TestPresenter的Dependency是什麼,TestPresenter的Dependency的Dependency是什麼。。。首先這樣做操作很是繁瑣,其次,這樣做,導緻代碼耦合程度非常高,我們改變其中一環的時候,就要做大量的代碼改動。

然而,如果我們使用dagger2,這些問題就可以迎刃而解了。dagger2用一個類似依賴工廠的東西,将所需的依賴統一管理起來,所有需要用到依賴的類都可以到這裡尋找相應的依賴,并且dagger2會自動搜尋這個類所用到的依賴的依賴,系統會自動識别這個依賴關系。

Dagger2的基本使用方法

Dagger2主要由2個部分組成:首先我們需要一個産生依賴的工廠Module,然後我們需要一個管理這些Module的管理者Component。

Module的實作(接前面的例子):

@Module
public class AppModule {

    @Provides
    public SchedulerProvider provideSchedulerProvider() {
        return SchedulerProvider.DEFAULT;
    }

    @Provides
    public AbsService provideApi() {
        return AbsService.getInstance();
    }

    @Provides
    public AbsService.AbsApi provideAbsApi() {
        return AbsService.getService();
    }

    @Provides
    public TestPresenter providePresenter(AbsService absService,SchedulerProvider schedulerProvider) {
        return new TestPresenter(absService,schedulerProvider);
    }
}
           

在上面的Module類的中,我們用@Module注解标注了這個類,告訴dagger2這個類是提供依賴的Module,下面很多個用@Provides注解标注的方法則是告訴dagger2這個方法用來提供依賴。如果需要提供單例的依賴則需要在前面,加上@Singleton注解。這個時候,可能有人會有疑問了,多層的依賴dagger是怎麼找的?dagger2尋找依賴的規則如下:

步驟1:首先查找@Module标注的類中是否存在提供依賴的方法。

步驟2:若存在提供依賴的方法,檢視該方法是否存在參數。

a:若存在參數,則按從步驟1開始依次初始化每個參數;

b:若不存在,則直接初始化該類執行個體,完成一次依賴注入。

步驟3:若不存在提供依賴的方法,則查找@Inject标注的構造函數,看構造函數是否存在參數。

a:若存在參數,則從步驟1開始依次初始化每一個參數

b:若不存在,則直接初始化該類執行個體,完成一次依賴注入。

通過這樣一個操作,dagger2就能直接自動的尋找所需的依賴了。

Component的實作:

@Component(modules = {AppModule.class})
public interface AppComponent {
    TestPresenter testPresenter();
}
           

或是

@Component(
        modules = AppModule.class
)
public interface AppComponent {
    TestActivityFragment2 inject(TestActivityFragment2 activity);
}
           

Component需要用 @Component修飾一下,來标注這是一個dagger2的Component,而不是一個普通的interface,用modules = AppModule.class來告訴dagger2要從哪個Module中去找依賴,注意如果有多個Module,可以和第一種方法一樣寫成數組的形式。

在Component中的方法是我們需要使用依賴的時候使用的,比如第一種,就比較直覺,我們需要TestPresenter 這個執行個體,直接定義這個方法,dagger2就會自動生成一個Dagger+Component名字(如DaggerAppComponent )這樣一個方法,這個方法就從AppComponent管理的AppModule中尋找依賴,傳回一個Presenter的執行個體。

然後在需要調用執行個體的時候隻需要像下面這樣做就可以完成執行個體化了:

public class TestActivityFragment2 extends Fragment {
    private TestPresenter mTestPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        AppComponent appComponent =    DaggerAppComponent.builder().appModule(new AppModule(this)).build();  
        mTestPresenter= appComponent.testPresenter();   
    }
}
           

對于第二種方式,我們需要這樣調用:

public class TestActivityFragment2 extends Fragment {
     @Inject
      TestPresenter mTestPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        AppComponent appComponent =  DaggerAppComponent.builder().appModule(new AppModule(this)).build();  
        appComponent.inject(this); 
    }
}
           

DaggerAppComponent實作這個方法的方式是,去TestActivityFragment2 裡面所有被 @Inject修飾的變量,然後調用 AppModule相應的Provider方法對相應類型提供依賴。對于這兩種方法,一般來說我會選擇第二種,寫起來比較簡便。

以上,我所了解的dagger的基本用法就這些了。