Dagger2 極速入門

Github地址

Dagger是一個快速的依賴注入框架,供Android和Java開發使用。以前由Square維護,現在轉交給Google,Github鏈接為:https://github.com/google/dagger

依賴注入

Dagger為依賴注入而生。什么是依賴?什么是注入?為什么要使用依賴注入?這是我們學習Dagger之前必須了解的。依賴就是一個類中要使用其他的類來完成某些工作,這樣一個類就依賴了另外一個類。比如在MainActivity中必須使用一個User類的對象,那么MainActivity就依賴了User類。

public class MainActivity extends AppCompatActivity {

    User mUser;//MainActivity依賴User類

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mUser = new User();//初始化mUser
        setContentView(R.layout.activity_main);
    }
}

一般我們直接在MainActivity中直接初始化mUser對象,但如果有天User類的構造方法中增加了一個參數,比如用戶名,那么所有調用User的無參構造方法的地方全部要修改,這顯然不是我們希望看到的。于是我們思考可不可以提供一個User的工廠類或者容器類專門負責User對象的創建,這樣User對象的創建就不會跟MainActivity發生耦合,不管User的構造方法如何變,都不會影響到MainActivity。那么代碼可能是這樣:

public class MainActivity extends AppCompatActivity {

    User mUser;//MainActivity依賴User類

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mUser = UserFactory.getUser()//通過工廠類注入mUser
        setContentView(R.layout.activity_main);
    }
}

那么mUser對象就不是在MainActivity創建,而是由UserFactory創建,設置給mUser對象,這就可以稱之為mUser被注入了,這樣MainActivity就不需要關心User對象是怎樣創建出來,對User對象創建的修改就不會影響到MainActivity里面的代碼,這就是依賴注入的好處的。這就好比我們打針,人體依賴藥液來治療疾病,但藥液并不是人體自己生產的,而是醫藥公司生產然后通過注射器注入到人體,而我們人體根本就無需關心藥液是如何被制造出來的。

Dagger的作用就是通過注解的方式,幫我們自動生成創建對象的工廠類。

Dagger 2使用

1. 添加依賴

可通過鏈接https://github.com/google/dagger/releases查找最新版本

dependencies {
    compile 'com.google.dagger:dagger:2.11'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
}

2. 添加注解@Inject

分別在MainActivity的User成員變量和User的構造方法上添加@Inject依賴。

public class MainActivity extends AppCompatActivity {

    //成員變量上添加注解
    @Inject
    User mUser;
}


public class User {

    String name;

    //構造方法上添加注解
    @Inject
    public User() {
        this.name  = "Leon";
    }

}

3. 創建Component類

事實上完成第二步后,MainActivity中成員mUser并沒有調用構造方法完成初始化,還需要一個類來完成注入,這就是Component類。
我們創建一個MainComponent接口,提供一個inject方法,其參數為將被注入的類MainActivity

public interface MainComponent {

    void inject(MainActivity activity);
}

然后,我們在Android Studio下選擇菜單build->Make Project,這時候,會在app模塊下build/generated/source/apt/debug/包名/目錄下生成三個文件DaggerMainComponentMainActivity_MembersInjectorUser_Factory。DaggerMainComponent即為接口MainComponent的實現類。

4. 注入

最后,我們可以使用生成的DaggerMainComponnet完成注入,成員變量mUser將被賦值。如果是老司機,是不是會覺得這跟ButterKnife.bind(this)有異曲同工之妙呢?

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //注入,內部會調用User的構造方法完成成員變量mUser的初始化
    DaggerMainComponent.builder().build().inject(this);
    //打印結果,mUser不為null
    Log.d(TAG, "onCreate: " + mUser.name);
}

Module使用

假如我想在一個Activity里面注入一個TextView,如下:

public class MainActivity extends AppCompatActivity {

    @Inject
    TextView mTextView;
}

如果按照上述步驟,就需要找到TextView的構造方法,加上一個@Inject注解,這個顯然是無法做到的。Module就是為了解決不能夠通過注解構造方法來創建一個實例的問題。我們創建一個TextViewMoudle類,使用@Module注解。另外需要提供一個方法返回一個TextView實例,并且用@Provides注解。

@Module
public class TextViewModule {

    @Provides
    TextView provideTextView(Context context) {
        return new TextView(context);
    }
}

provideTextView方法有個Context參數,需要外界傳入到TextViewModule,這里給TextViewModule提供一個帶有Context參數的構造方法。另外還需要提供個provideContext方法返回上下文,因為Dagger框架調用provideTextView方法獲取一個TextView實例時,發現要傳一個Context類型的參數,這時候他會查找被@Provides注解并且返回值為Context類型的方法獲取一個Context實例傳入provideTextView方法。

@Module
public class TextViewModule {
    //保存一個上下文成員變量
    private Context mContext;

    //構造方法接收一個上下文
    public TextViewModule(Context context) {
        this.mContext = context;
    }

    @Provides
    TextView provideTextView(Context context) {
        return new TextView(context);
    }

    
    @Provides
    Context provideContext() {
        return mContext;
    }
}

接下來還需要在MainComponent接口上指定TextViewModule。然后點擊菜單選項build->Make Project,這時又會在build/generated/source/apt/debug/包名/目錄下生成兩個新文件TextViewModule_ProvideContextFactoryTextViewModule_ProvideTextViewFactory

@Component(modules = TextViewModule.class)
public interface MainComponent {

    void inject(MainActivity activity);
}

最后在注入時創建一個TextViewModule傳入,表示告訴Dagger框架可以從TextViewModule中獲取TextView實例。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //傳入TextViewMoudle
    DaggerMainComponent.builder().textViewModule(new TextViewModule(this)).build().inject(this);
    FrameLayout frameLayout = (FrameLayout) findViewById(R.id.frame);
    //mTextView已被注入,不為null
    mTextView.setText(mUser.name);
    frameLayout.addView(mTextView);
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容

  • Dagger2 轉載請注明原作者,如果你覺得這篇文章對你有幫助或啟發,可以關注打賞。 前言本文翻譯自Google ...
    輕云時解被占用了閱讀 6,721評論 4 31
  • 注:本文是小生自學時做(fanyi)的筆記,可能含有少兒不宜的誤導性內容,學習Dagger請移步原博。原博地址:h...
    烏龜愛吃肉閱讀 557評論 0 0
  • 文章翻譯自Dagger官網,翻譯水平有限,見諒。 引入 引用官網的引入說明,上面的部分都好理解,就是簡單的comp...
    one_cup閱讀 644評論 0 0
  • 將一個可迭代/遍歷的對象組成一個索引序列,利用他可以同時獲得索引與值 可以指定索引起始值
    cctse閱讀 296評論 0 0
  • 在我前一篇文章Log4j2 簡單使用中介紹了一些Log4j2的簡單使用方法。下面來做一些進階介紹。 使用屬性 在復...
    樂百川閱讀 5,816評論 0 4