什么是dagger2
Dagger是為Android和Java平臺(tái)提供的一個(gè)完全靜態(tài)的,在編譯時(shí)進(jìn)行依賴注入的框架膳汪,原來(lái)是由Square公司維護(hù)芒珠,現(xiàn)在由Google維護(hù)。一句話缨伊,dagger2其實(shí)就是一套依賴注入框架。那么什么是依賴注入呢进宝?
具體含義是:當(dāng)某個(gè)角色(可能是一個(gè)Java實(shí)例刻坊,調(diào)用者)需要另一個(gè)角色(另一個(gè)Java實(shí)例,被調(diào)用者)的協(xié)助時(shí)党晋,在 傳統(tǒng)的程序設(shè)計(jì)過(guò)程中谭胚,通常由調(diào)用者來(lái)創(chuàng)建被調(diào)用者的實(shí)例。但在dagger2里未玻,創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來(lái)完成灾而,而是由dagger2來(lái)完成,然后注入調(diào)用者扳剿,因此也稱為依賴注入旁趟。
為什么需要dagger2
說(shuō)實(shí)話,剛接觸dagger2的時(shí)候我也是一臉懵逼庇绽,這個(gè)東西這么繁瑣锡搜,為什么要用它呢?這個(gè)問(wèn)題其實(shí)就是為何我們需要依賴注入瞧掺。有本書上這樣寫道:依賴注入不是目的耕餐,它是一系列工具和手段,最終的目的是幫助我們開發(fā)出松散耦合辟狈、可維護(hù)肠缔、可測(cè)試的代碼和程序∩仙拢可想而知桩砰,其最終目的是實(shí)現(xiàn)解耦。何為解耦释簿?怎么解耦亚隅?舉個(gè)例子說(shuō)明一下:
前面我們講到MVP架構(gòu),我們的Presenter層構(gòu)造函數(shù)可能需要一些參數(shù):訪問(wèn)服務(wù)端的AbsService實(shí)例庶溶,做網(wǎng)絡(luò)請(qǐng)求線程切換的SchedulerProvider 煮纵,如下,
public class TestPresenter extends BasePresenter<TestView> {
AbsService mAbsService;
SchedulerProvider mSchedulerProvider;
public TestPresenter(AbsService absService,SchedulerProvider schedulerProvider) {
this.mAbsService=absService;
this.mSchedulerProvider=schedulerProvider;
}
}
那么我們?cè)趯?shí)例化這個(gè)Presenter的時(shí)候就需要這樣做:
AbsService mAbsService=AbsService.getInstance();
SchedulerProvider schedulerProvider=SchedulerProvider.DEFAULT;
TestPresenter testPresenter=new TestPresenter(mAbsService,schedulerProvider);
需要把TestPresenter需要的參數(shù)一個(gè)個(gè)的實(shí)例化偏螺,然后作為參數(shù)傳給它行疏。試想一下,如果我們的AbsService和SchedulerProvider 還需要很多參數(shù)套像,或者TestPresenter需要3個(gè)乃至更多的參數(shù)酿联,那我們實(shí)例化一個(gè)TestPresenter要做的操作是不是太多了,這樣實(shí)在是太夸張了,我們只是需要一個(gè)TestPresenter實(shí)例而已贞让,就必須知道TestPresenter的Dependency是什么周崭,TestPresenter的Dependency的Dependency是什么。喳张。续镇。首先這樣做操作很是繁瑣,其次销部,這樣做摸航,導(dǎo)致代碼耦合程度非常高,我們改變其中一環(huán)的時(shí)候舅桩,就要做大量的代碼改動(dòng)酱虎。
然而,如果我們使用dagger2江咳,這些問(wèn)題就可以迎刃而解了逢净。dagger2用一個(gè)類似依賴工廠的東西,將所需的依賴統(tǒng)一管理起來(lái)歼指,所有需要用到依賴的類都可以到這里尋找相應(yīng)的依賴爹土,并且dagger2會(huì)自動(dòng)搜索這個(gè)類所用到的依賴的依賴,系統(tǒng)會(huì)自動(dòng)識(shí)別這個(gè)依賴關(guān)系踩身。
Dagger2的基本使用方法
Dagger2主要由2個(gè)部分組成:首先我們需要一個(gè)產(chǎn)生依賴的工廠Module胀茵,然后我們需要一個(gè)管理這些Module的管理員Component。
Module的實(shí)現(xiàn)(接前面的例子):
@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注解標(biāo)注了這個(gè)類琼娘,告訴dagger2這個(gè)類是提供依賴的Module,下面很多個(gè)用@Provides注解標(biāo)注的方法則是告訴dagger2這個(gè)方法用來(lái)提供依賴。如果需要提供單例的依賴則需要在前面附鸽,加上@Singleton注解脱拼。這個(gè)時(shí)候,可能有人會(huì)有疑問(wèn)了坷备,多層的依賴dagger是怎么找的熄浓?dagger2尋找依賴的規(guī)則如下:
步驟1:首先查找@Module標(biāo)注的類中是否存在提供依賴的方法。
步驟2:若存在提供依賴的方法省撑,查看該方法是否存在參數(shù)赌蔑。
a:若存在參數(shù),則按從步驟1開始依次初始化每個(gè)參數(shù)竟秫;
b:若不存在娃惯,則直接初始化該類實(shí)例,完成一次依賴注入肥败。
步驟3:若不存在提供依賴的方法趾浅,則查找@Inject標(biāo)注的構(gòu)造函數(shù)愕提,看構(gòu)造函數(shù)是否存在參數(shù)。
a:若存在參數(shù)潮孽,則從步驟1開始依次初始化每一個(gè)參數(shù)
b:若不存在揪荣,則直接初始化該類實(shí)例筷黔,完成一次依賴注入往史。
通過(guò)這樣一個(gè)操作,dagger2就能直接自動(dòng)的尋找所需的依賴了佛舱。
Component的實(shí)現(xiàn):
@Component(modules = {AppModule.class})
public interface AppComponent {
TestPresenter testPresenter();
}
或是
@Component(
modules = AppModule.class
)
public interface AppComponent {
TestActivityFragment2 inject(TestActivityFragment2 activity);
}
Component需要用 @Component修飾一下椎例,來(lái)標(biāo)注這是一個(gè)dagger2的Component,而不是一個(gè)普通的interface请祖,用modules = AppModule.class來(lái)告訴dagger2要從哪個(gè)Module中去找依賴订歪,注意如果有多個(gè)Module,可以和第一種方法一樣寫成數(shù)組的形式肆捕。
在Component中的方法是我們需要使用依賴的時(shí)候使用的刷晋,比如第一種,就比較直觀慎陵,我們需要TestPresenter 這個(gè)實(shí)例眼虱,直接定義這個(gè)方法,dagger2就會(huì)自動(dòng)生成一個(gè)Dagger+Component名字(如DaggerAppComponent )這樣一個(gè)方法席纽,這個(gè)方法就從AppComponent管理的AppModule中尋找依賴捏悬,返回一個(gè)Presenter的實(shí)例。
然后在需要調(diào)用實(shí)例的時(shí)候只需要像下面這樣做就可以完成實(shí)例化了:
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();
}
}
對(duì)于第二種方式润梯,我們需要這樣調(diào)用:
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實(shí)現(xiàn)這個(gè)方法的方式是过牙,去TestActivityFragment2 里面所有被 @Inject修飾的變量,然后調(diào)用 AppModule相應(yīng)的Provider方法對(duì)相應(yīng)類型提供依賴纺铭。對(duì)于這兩種方法寇钉,一般來(lái)說(shuō)我會(huì)選擇第二種,寫起來(lái)比較簡(jiǎn)便舶赔。