dagger2 循序漸進(jìn)學(xué)習(xí)(包會(huì))(三) 實(shí)例1,application中的應(yīng)用

文章索引
dagger2 循序漸進(jìn)學(xué)習(xí)(一)依賴(lài)注入基礎(chǔ)知識(shí)(包會(huì))
dagger2 循序漸進(jìn)學(xué)習(xí)(二)
dagger2 循序漸進(jìn)學(xué)習(xí)(三) 實(shí)例1,application中的應(yīng)用

前兩篇dagger2的文章介紹了其基本的使用方法,但其使用中還有很多重要的細(xì)節(jié)需要我們掌握熬芜,我認(rèn)為在實(shí)例中學(xué)習(xí)比羅列一大堆的理論名稱(chēng)解釋要來(lái)的實(shí)在。所以接下來(lái)每篇文章主要以一個(gè)馬上能應(yīng)用起來(lái)的小實(shí)例去解釋一個(gè)個(gè)知識(shí)點(diǎn)福稳,文章在精不在多涎拉,希望我寫(xiě)的文字能達(dá)到這樣的效果吧!

dagger2 知識(shí)點(diǎn)

一的圆、@Inject

先來(lái)說(shuō)下上一篇文章dagger2 循序漸進(jìn)學(xué)習(xí)(二) 鼓拧,文中的activity

public class LoginActivity extends AppCompatActivity  implements ILoginContract.ILoginView{
@Inject//這里加注解
LoginPresenter presenter;


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

@Override
public void loginok() {

}

@Override
public void loginErro() {

}
}

文中的presenter:

public class LoginPresenter implements     ILoginContract.ILoginPresenter {
ILoginContract.ILoginView view;

@Inject//這里注解
public LoginPresenter(ILoginContract.ILoginView view) {
this.view = view;
}

@Override
public void login(String name, String pwd) {
}
}

有沒(méi)有發(fā)現(xiàn)

Paste_Image.png

presenter注入的類(lèi)并沒(méi)有遵循依賴(lài)倒置的原則,就是說(shuō)沒(méi)有依賴(lài)presenter的接口類(lèi)略板,如果我們改成其接口類(lèi)之后運(yùn)行就會(huì)報(bào)錯(cuò)

Paste_Image.png

那這是為什么呢毁枯,可以看出原因就在@Inject
依賴(lài)注入中第一個(gè)并且是最重要的就是 @Inject 注解。JSR-330標(biāo)準(zhǔn)中的一部分叮称,標(biāo)記那些應(yīng)該被依賴(lài)注入框架提供的依賴(lài)种玛。在Dagger 2中有3種不同的方式來(lái)提供依賴(lài):

構(gòu)造器注入,

@Inject標(biāo)注在構(gòu)造器上其實(shí)有兩層意思瓤檐。

①告訴Dagger2可以使用這個(gè)構(gòu)造器構(gòu)建對(duì)象赂韵。如 LoginPresenter 類(lèi)構(gòu)造方法上的@Inject

②注入構(gòu)造器所需要的參數(shù)的依賴(lài)。 如 Pot 類(lèi)挠蛉,構(gòu)造上的Rose會(huì)被注入祭示。又如 LoginPresenter 類(lèi)構(gòu)造方法上的@Inject實(shí)現(xiàn)①的功能外,它本身還需要ILoginContract.ILoginView的依賴(lài)谴古,此時(shí)的注入實(shí)際就在dagger2框架中 LoginModule中提供的质涛,只是什么時(shí)候怎么提供的我們暫時(shí)不得而知

Paste_Image.png

構(gòu)造器注入的局限:如果有多個(gè)構(gòu)造器稠歉,我們只能標(biāo)注其中一個(gè),無(wú)法標(biāo)注多個(gè)汇陆。

屬性注入

如 LoginActivity 類(lèi)怒炸,標(biāo)注在屬性上。被標(biāo)注的屬性不能使用 private 修飾毡代,否則無(wú)法注入阅羹。

屬性注入也是Dagger2中使用最多的一個(gè)注入方式。
看到這里應(yīng)該明白了LoginPresenter是如何注入到LoginActivity中的了:就是1在LoginActivity屬性上標(biāo)注@Inject 教寂,2在LoginPresenter的構(gòu)造方法上同時(shí)標(biāo)注@Inject捏鱼,編譯過(guò)程中,dagger2就知道了LoginActivity的presenter屬性需要注入酪耕,接下來(lái)就去尋找哪里可以提供导梆,其中一項(xiàng)就是就是找有沒(méi)有相應(yīng)類(lèi)的構(gòu)造器用@Inject標(biāo)注的,如果有就用這個(gè)構(gòu)造器構(gòu)造后注入activity因妇。所以當(dāng)我們把LoginActivity中的屬性改成ILoginPresenter接口類(lèi)型的時(shí)候问潭,dagger2就找不到了他的構(gòu)造器了,所以就報(bào)錯(cuò)了婚被。

方法注入

Paste_Image.png

標(biāo)注在public方法上,Dagger2會(huì)在構(gòu)造器執(zhí)行之后立即調(diào)用這個(gè)方法梳虽。

方法注入和屬性注入基本上沒(méi)有區(qū)別址芯, 那么什么時(shí)候應(yīng)該使用方法注入呢?

比如該依賴(lài)需要this對(duì)象的時(shí)候窜觉,使用方法注入可以提供安全的this對(duì)象谷炸,因?yàn)?strong>方法注入是在構(gòu)造器之后執(zhí)行的。

比如google mvp dagger2中禀挫,給View設(shè)置Presenter的時(shí)候可以這樣使用方法注入旬陡。

/**
 * Method injection is used here to safely reference {@code    this} after the object is created.
 * For more information, see Java Concurrency in Practice.
 */
@Inject
void setupListeners() {
 mTasksView.setPresenter(this);
 }

二、@Component

@Inject 注解是JSR-330中定義的注解语婴,在 javax.inject 包中描孟。
這個(gè)注解本身并沒(méi)有作用,它需要依賴(lài)于注入框架才具有意義砰左,用來(lái)標(biāo)記需要被注入框架注入的方法匿醒,屬性,構(gòu)造缠导。
而Dagger2則是用 Component 來(lái)完成依賴(lài)注入的廉羔, @Component 可以說(shuō)是Dagger2中最重要的一個(gè)注解。
@Componentpublic interface MainActivityComponent { void inject(MainActivity activity);}

以上是定義一個(gè)Component的方式僻造。使用接口定義憋他,并且 @Component 注解孩饼。
命名方式推薦為: 目標(biāo)類(lèi)名+Component ,在編譯后Dagger2就會(huì)為我們生成 DaggerXXXComponent 這個(gè)類(lèi)竹挡,它是我們定義的 xxxComponent 的實(shí)現(xiàn)镀娶,在目標(biāo)類(lèi)中使用它就可以實(shí)現(xiàn)依賴(lài)注入了。
Component中一般使用兩種方式定義方法此迅。
void inject(目標(biāo)類(lèi) obj); Dagger2會(huì)從目標(biāo)類(lèi)開(kāi)始查找@Inject注解汽畴,自動(dòng)生成依賴(lài)注入的代碼,調(diào)用inject可完成依賴(lài)的注入耸序。
Object getObj(); 如: LoginPresenter getLoginPresentert();Dagger2會(huì)到LoginPresenter類(lèi)中找被@Inject注解標(biāo)注的構(gòu)造器忍些,自動(dòng)生成提供LoginPresenter依賴(lài)的代碼,這種方式一般為其他Component提供依賴(lài)坎怪。(一個(gè)Component可以依賴(lài)另一個(gè)Component罢坝,后面會(huì)說(shuō))

Component和Inject的關(guān)系如下:


Dagger2框架以Component中定義的方法作為入口,到目標(biāo)類(lèi)中尋找JSR-330定義的@Inject標(biāo)注搅窿,生成一系列提供依賴(lài)的Factory類(lèi)和注入依賴(lài)的Injector類(lèi)嘁酿。
而Component則是聯(lián)系Factory和Injector,最終完成依賴(lài)的注入男应。

三闹司、@Module和@Provides

使用@Inject標(biāo)記構(gòu)造器提供依賴(lài)是有局限性的,比如說(shuō)我們需要注入的對(duì)象是第三方庫(kù)提供的沐飘,我們無(wú)法在第三方庫(kù)的構(gòu)造器上加上@Inject注解游桩。
或者,我們使用依賴(lài)倒置的時(shí)候耐朴,因?yàn)樾枰⑷氲膶?duì)象是抽象的借卧,@Inject也無(wú)法使用,因?yàn)槌橄蟮念?lèi)并不能實(shí)例化比如咱們需要ILoginPresenter的接口類(lèi)的依賴(lài)筛峭,會(huì)出現(xiàn)文中最開(kāi)始的那個(gè)錯(cuò)誤铐刘;

這個(gè)時(shí)候就需要Module了。
先清除LoginPresenter中的@Inject

Paste_Image.png

并把LoginAcitivity中的依賴(lài)改成接口類(lèi)型

Paste_Image.png

@Module標(biāo)記在LoginModule類(lèi)上面影晓,@Provodes標(biāo)記在方法上镰吵,表示可以通過(guò)這個(gè)方法獲取依賴(lài)。

Paste_Image.png

在@Component中指定Module


Paste_Image.png

這樣就完了俯艰,ok了捡遍。測(cè)測(cè),沒(méi)有問(wèn)題竹握;
@Module和@Provides的作用:
@Module需要和@Provide是需要一起使用的時(shí)候才具有作用的画株,并且@Component也需要指定了該Module的時(shí)候。

@Module是告訴Component,可以從這里獲取依賴(lài)對(duì)象谓传。Component就會(huì)去找被@Provide標(biāo)注的方法蜈项,相當(dāng)于構(gòu)造器的@Inject,可以提供依賴(lài)续挟。

還有一點(diǎn)要說(shuō)的是紧卒,@Component可以指定多個(gè)@Module的,如果需要提供多個(gè)依賴(lài)的話(huà)诗祸。

并且Component也可以依賴(lài)其它Component存在跑芳。
如此便解決上面提到的問(wèn)題;回顧一下這四個(gè)最重要的注解的用法直颅。接下來(lái)我們研究個(gè)小實(shí)例博个。

實(shí)例

這個(gè)實(shí)例就是我們經(jīng)常要實(shí)現(xiàn)的application中retrofit的應(yīng)用。為了節(jié)省資源提高性能功偿,要求我們?cè)谑褂胷etrofit時(shí)候盆佣,整個(gè)app中retrofit是單例的,然后再用他create相應(yīng)的api的接口類(lèi)實(shí)例以往我們經(jīng)常會(huì)寫(xiě)一大堆代碼和模式來(lái)實(shí)現(xiàn)其單例械荷,在dagger中這一切變得簡(jiǎn)單共耍。下面開(kāi)始擼代碼:
相關(guān)的第三方庫(kù)的依賴(lài)就不寫(xiě)了;
api的請(qǐng)求接口是這樣?jì)饍旱?/p>

public interface ApiService {
@GET("/users/{user}/repos")
Observable<ArrayList<String>> getRepoData(@Path("user") String user);
}

再上個(gè)module

@Module
public class ServiceModule {

@Provides
public OkHttpClient provideOkHttpClient() {
    OkHttpClient okHttpClient ;
    OkHttpClient.Builder builder= new OkHttpClient.Builder();
    okHttpClient=builder.readTimeout(60 * 1000, TimeUnit.MILLISECONDS)
            .connectTimeout(60 * 1000, TimeUnit.MILLISECONDS)
            .build();
    return okHttpClient;
}

@Provides
public Retrofit provideRetrofit(Application application, OkHttpClient okHttpClient){
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(application.getString(R.string.api_host))
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rx適配器
            .addConverterFactory(GsonConverterFactory.create()) // 添加Gson轉(zhuǎn)換器
            .client(okHttpClient)
            .build();
    return retrofit;
}
@Singleton
@Provides
protected ApiService provideGitHubService(Retrofit retrofit) {

    return retrofit.create(ApiService.class);
}

}

再來(lái)個(gè)module

@Module
public class AppModule {
private final Application application;

public AppModule(Application application) {
    this.application = application;
}

@Provides
public Application provideApplication() {
    return application;
}

}

那么再來(lái)看我們的application類(lèi)中

public class App extends Application {
private  AppComponent appComponent;
@Override
public void onCreate() {
    super.onCreate();
   appComponent=
           DaggerAppComponent.builder()
           .appModule(new AppModule(this))
           .serviceModule(new ServiceModule())
           .build();
}

public  AppComponent getAppComponent() {
    return appComponent;
}
}

眼尖的同學(xué)看到了@Singleton吨瞎,這個(gè)先不說(shuō)痹兜,其他的不用我多說(shuō),相信前面都看懂了的同學(xué)颤诀,這幾個(gè)類(lèi)完全能看懂佃蚜。

@Singleton顧名思義,就是單例啊着绊,但是這個(gè)單例可不是怎么用都是單例。通過(guò)測(cè)試熟尉,我們發(fā)現(xiàn)當(dāng)重新build一個(gè)Component的時(shí)候归露,這個(gè)單例也是新的,所以準(zhǔn)確的說(shuō) 斤儿,它的作用只是保證依賴(lài)在@Component中是唯一的剧包,可以理解為“局部單例”。所以在application中實(shí)例化Component往果,其他地方用到它的時(shí)候就需要先在application獲取appComponent進(jìn)行注操作疆液。
通過(guò)這個(gè)方法,當(dāng)然如果也可以把他定義為static方法

public  AppComponent getAppComponent() {
return appComponent;
}

接下來(lái)我們遵循循序漸進(jìn)的原則dagger2還有部分知識(shí)點(diǎn)會(huì)在后面的文章繼續(xù)和大家分享陕贮,相信通過(guò)循序漸進(jìn)的邊學(xué)邊實(shí)踐的方式堕油,學(xué)習(xí)起來(lái)更扎實(shí),不像一口吞個(gè)胖子樣!掉缺!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卜录,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子眶明,更是在濱河造成了極大的恐慌艰毒,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搜囱,死亡現(xiàn)場(chǎng)離奇詭異丑瞧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蜀肘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)绊汹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人幌缝,你說(shuō)我怎么就攤上這事灸促。” “怎么了涵卵?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵浴栽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我轿偎,道長(zhǎng)典鸡,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任坏晦,我火速辦了婚禮萝玷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昆婿。我一直安慰自己球碉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布仓蛆。 她就那樣靜靜地躺著睁冬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪看疙。 梳的紋絲不亂的頭發(fā)上豆拨,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音能庆,去河邊找鬼施禾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛搁胆,可吹牛的內(nèi)容都是我干的弥搞。 我是一名探鬼主播邮绿,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拓巧!你這毒婦竟也來(lái)了斯碌?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肛度,失蹤者是張志新(化名)和其女友劉穎傻唾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體承耿,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冠骄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了加袋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凛辣。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖职烧,靈堂內(nèi)的尸體忽然破棺而出扁誓,到底是詐尸還是另有隱情,我是刑警寧澤蚀之,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布蝗敢,位于F島的核電站,受9級(jí)特大地震影響足删,放射性物質(zhì)發(fā)生泄漏寿谴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一失受、第九天 我趴在偏房一處隱蔽的房頂上張望讶泰。 院中可真熱鬧,春花似錦拂到、人聲如沸痪署。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惠桃。三九已至,卻和暖如春辖试,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劈狐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工罐孝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肥缔。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓莲兢,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子改艇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容