Dagger2使用

Dagger2使用

命名規約

  • @Provides方法用provide前綴命名
  • @Module 用Module后綴命名
  • @Component 以Component作為后綴

簡單的說,就是一個工廠模式,由Dagger負責創建工廠,幫忙生產instance。遵從Java規范JSR 330,可以使用這些注解。現在不研究Dagger2是如何根據注解去生成工廠的,先來看看工廠是什么東西,理解為什么可以實現了DI(Dependency Injection),如何創建IoC(Inverse of Control)容器。


  • Dagger2是通過依賴注入完成類的初始化。
    這個過程需要三部分:
    #1 依賴提供方(生產者)
    #2 依賴注入容器(橋梁)
    #3 依賴需求方(消費者)
    image.png

Dagger2是怎么選擇依賴提供的呢,規則是這樣的:

步驟1:查找Module中是否存在創建該類的方法。
步驟2:若存在創建類方法,查看該方法是否存在參數
步驟2.1:若存在參數,則按從步驟1開始依次初始化每個參數
步驟2.2:若不存在參數,則直接初始化該類實例,一次依賴注入到此結束
步驟3:若不存在創建類方法,則查找Inject注解的構造函數,看構造函數是否存在參數
步驟3.1:若存在參數,則從步驟1開始依次初始化每個參數
步驟3.2:若不存在參數,則直接初始化該類實例,一次依賴注入到此結束

  • 在使用@Component的時候必須要提供scope范圍,標準范圍是@Singleton
  • @Component在使用@Module的時候必須匹配相同的scope
  • 能使用Singleton的時候,要注意標注,否則默認多例

總結:

  • @Inject
    主要有兩個作用
    #1 作為依賴注提供方
    使用@Inject注解構造方法。
    注解構造函數,讓Dagger2幫我們實例化該,并注入。
    #2 作為依賴需求方:
    使用@Inject注解成員。
    如果一個成員變量@Inject注解修飾,并且成員類構造函數也被@Inject注解,那么dagger2幫我們實例化該成員類,并注入。
    通常在需要依賴的地方使用這個注解。換句話說,你用它告訴Dagger這個類或者字段需要依賴注入。這樣,Dagger就會構造一個這個類的實例并滿足他們的依賴。

使用@Inject可以讓IoC容器負責生成instance,如果沒有這個注解,dagger將不認識,當做普通類,無法代理

  • @Module
    #1 @Module 注解,負責管理依賴。
    Module 其實是一個簡單工廠模式,Module 里面的方法都是創建相應類實例的方法。
    #2 通過@Module獲得第三方類庫的對象。
    #3 @Module是一個依賴提供方的合集。
@Module
public class AModule {

    @Provides
    public Gson provideGson(){
        return new Gson();
    }
}
  • @Provides
    #1 注解@Module 中的方法
    在modules中,我們定義的方法是用這個注解,以此來告訴Dagger我們想要構造對象并提供這些依賴。

  • @Component
    #1 @Component一般用來注解接口
    #2 負責在@Inject@Module之間建立連接。
    也可以說是@Inject和@Module的橋梁,它的主要作用就是連接這兩個部分。
    #3 實例化@Inject注解的時,遇到沒有構造函數的類依賴,則該依賴由@Module修飾的類提供。
    #4 依賴注入容器只是一個接口interface

Component需要引用到目標類的實例,Component會查找目標類中用Inject注解標注的屬性,查找到相應的屬性后會接著查找該屬性對應的用Inject標注的構造函數(這時候就發生聯系了),剩下的工作就是初始化該屬性的實例并把實例進行賦值。因此我們也可以給Component叫另外一個名字注入器(Injector)

Component注解的類,再編譯之后,會生產一個以Dagger+類名的一個類,如下面的MainComponent會生成類DaggerMainComponent(補充一點,Kotlinkapt編譯生成類的位置:\build\generated\source\kapt\debug),我們需要在目標類MainActivity中加入下面代碼

DaggerMainComponent.builder()
                .build()
                .inject(this)

DaggerMainComponent使用了建造者設計模式,inject方法是我們MainComponent中定義的,這樣目標類就和Component建立了聯系.Component會去遍歷使用@Inject注解的常量,然后去查找對應的類是否有@Inject注解的構造方法,如果沒有就會報異常.

@Component {modules = {HeaterModule.class, PumperModule.class}}
public interface MachineComponent {
  void inject(CoffeeMachine machine);
}

dagger中Component就是最頂級的入口,dagger為之生成了工廠類 DaggerMachineComponent,目標是構建CoffeeMachine, 在CoffeeMachine中使用了Injection,那么依賴要由工廠類來提供。工廠類是根據modules的參數來找依賴綁定的。

本例中,指向了HeaterModule, PumperModule,意思是CoffeeMachine的依賴要從這些module里找。

工廠名稱生成規則

  • 如果Component是接口, 則生成Dagger+接口名

  • 如果Component是內部接口,比如本例,則生成Dagger+類名+ _+ 接口名

  • @Scope
    Scopes可是非常的有用,Dagger2可以通過自定義注解限定注解作用域。后面會演示一個例子,這是一個非常強大的特點,因為就如前面說的一樣,沒 必要讓每個對象都去了解如何管理他們的實例。在scope的例子中,我們用自定義的@PerActivity注解一個類,所以這個對象存活時間就和 activity的一樣。簡單來說就是我們可以定義所有范圍的粒度(@PerFragment, @PerUser, 等等)。

  • Qualifier
    當類的類型不足以鑒別一個依賴的時候,我們就可以使用這個注解標示。例如:在Android中,我們會需要不同類型的context,所以我們就可以定義 qualifier注解“@ForApplication”和“@ForActivity”,這樣當注入一個context的時候,我們就可以告訴 Dagger我們想要哪種類型的context。

/**
 * View層,負責界面的展示
 */
public class TestActivity extends AppCompatActivity implements IView{
//當一個成員變量被@Inject注解修飾,并且它的類型構造函數也被@Inject注解修飾,dagger2就會自動實例化該成員類型,并注入到該成員變量
    @Inject
    TestPresent mPresent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        DaggerTestComponent.builder().testModule(new TestModule(this)).build().inject(this);//@Component負責連接起@Inject和@Module注解
        mPresent.updateUI();
    }
    @Override
    public void updateUI(String text) {
        ((TextView)findViewById(R.id.textview)).setText(text);
    }
}
/**
 * Present類,調用Model層的業務方法,更新View層的界面展示
 */
public class TestPresent {
    IView mView;
    @Inject
    TestModel mModel;//Dagger2遇到@Inject標記的成員屬性,就會去查看該成員類的構造函數,如果構造函數也被@Inject標記,則會自動初始化,完成依賴注入。
    //TestPresent的構造函數也被@Inject注解修飾
    @Inject
    public TestPresent(IView view){
        this.mView=view;
    }
    public void updateUI(){
        mView.updateUI(mModel.getText());
    }
}
/**
 * Model類,實現具體的業務邏輯
 */
public class TestModel {
    //構造函數用@Inject修飾
    @Inject
    public TestModel(){
    }
    public String getText(){
        return "Dagger2應用實踐...";
    }
}
/**
 * Module類提供那些沒有構造函數的類的依賴,如第三方類庫,系統類,接口類
 */
@Module
public class TestModule {
    private IView mView;
    public TestModule(IView iView){
        this.mView=iView;
    }
    //@Provides注解的方法,提供IView類的依賴。
    @Provides
    public IView provideIView(){
        return this.mView;
    }
}
/**
 *Component必須是一個接口類或者抽象
 */
@Component(modules = TestModule.class)
public interface TestComponent {
    void inject(TestActivity testActivity);
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容