dagger2 的安卓支持庫的使用

將以下內(nèi)容添加到build.gradle中(未包括dagger2基本依賴)

dependencies {
  compile 'com.google.dagger:dagger-android:2.x'
  compile 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
  annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
}

為什么要使用dagger2的安卓支持庫

很多Android框架類,比如Activity和Fragment浦译,由系統(tǒng)本身實例化,如果dagger可以創(chuàng)造所有注入對象命贴,它可以工作得最好梢莽。相反的,如果你不得不在生命周期的方法中執(zhí)行注入對象注入臼朗,這樣意味著有些類會看起來像這樣邻寿。

public class FrombulationActivity extends Activity {
  @Inject Frombulator frombulator;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // DO THIS FIRST. Otherwise frombulator might be null!
    ((SomeApplicationBaseType) getContext().getApplicationContext())
        .getApplicationComponent()
        .newActivityComponentBuilder()
        .activity(this)
        .build()
        .inject(this);
    // ... now you can write the exciting code
  }
}

這樣做有幾個問題
1.復制粘貼代碼會使重構變得困難,當越來越多的開發(fā)者復制粘貼那段代碼视哑,很少有人知道它實際做了什么绣否。
2.更根本的是,它需要請求注入(FrombulationActivity)的類型來了解其注入器挡毅。即使這是通過接口而不是具體類型完成的蒜撮,它打破了依賴注入的核心原則:類不應該知道注入的方式。
所以dagger2開發(fā)者弄出了這么一套框架跪呈。
怎么實現(xiàn)呢段磨?
1.安裝AndroidInjiectionModule在應用程序中以確保這些基本類型所需的所有綁定都可用取逾。(就是引入依賴)
2.首先寫一個SubComponent接口擴展AndroidInjector<YourActivity>,該接口有繼承了AndroidInjector.Builder<YourActivity>的方法(注意注釋)

@Subcomponent(modules = ...)
public interface YourActivitySubcomponent extends AndroidInjector<YourActivity> {
  @Subcomponent.Builder
  public abstract class Builder extends AndroidInjector.Builder<YourActivity> {}
}

3.在定義完Subcomponent后,添加它到你的component分層結構中薇溃,具體做法是定義一個綁定了subcomponent builder的module菌赖,再將該module添加到注入你Applicationa的component中。

@Module(subcomponents = YourActivitySubcomponent.class)
abstract class YourActivityModule {
  @Binds
  @IntoMap
  @ActivityKey(YourActivity.class)
  abstract AndroidInjector.Factory<? extends Activity>
      bindYourActivityInjectorFactory(YourActivitySubcomponent.Builder builder);
}

@Component(modules = {..., YourActivityModule.class})
interface YourApplicationComponent {}

Pro-tip:如果你的Subcomponent和它的builder沒有其他方法或者supertypes沐序,你可以使用ContributesAndroidInjector去自動生成上面兩個步驟中的代碼琉用。添加一個抽象module并返回你的activity,并用@ContributesAndroidInjector策幼,然后聲明你想要安裝到subcomponent中的modules邑时,如果這個subcomponent需要scopes,在該方法中聲明注釋特姐。

@ActivityScope
@ContributesAndroidInjector(modules = { /* modules to install into the subcomponent */ })
abstract YourActivity contributeYourActivityInjector();

4.讓你的Application實現(xiàn)HasActivityInjector并且@Inject一個DispatchingAndroidInjector<Activity>并且從activityInjector方法中返回

public class YourApplication extends Application implements HasActivityInjector {
  @Inject DispatchingAndroidInjector<Activity> dispatchingActivityInjector;

  @Override
  public void onCreate() {
    super.onCreate();
    DaggerYourApplicationComponent.create()
        .inject(this);
  }

  @Override
  public AndroidInjector<Activity> activityInjector() {
    return dispatchingActivityInjector;
  }
}

5.在你的Activity.onCreate()方法中在調(diào)用super.onCreate()方法前調(diào)用AndroidInjection.inject(this)方法

public class YourActivity extends Activity {
  public void onCreate(Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
  }
}

6.完成

那么它是怎么工作的呢晶丘?

AndroidInjection.inject()得到了來自Application的DispatchingAndroidInjector<Activity>并將您的activity傳遞給inject(Activity)。DispatchingAndroidInjector查找AndroidInjector.Factory作為您的activity的類(這是YourActivitySubcomponent.Builder)唐含,創(chuàng)建了 AndroidInjector(這是YourActivitySubcomponent)浅浮,并傳遞你的activity給inject(YourActivity)。

注入Fragment對象
注入一個Fragment和注入一個Activity一樣簡單捷枯。用同樣的方法定義你的subcomponent滚秩,用Fragment.@FragmentKey和HasFragmentInjector
類型代替Activity.@ActivityKey和HasActivityInjector
用在onAttach()注入Fragments代替在onCreate()中的注入。
和在Activitys中定義modules不同淮捆,你有在何時為Fragments安裝modules的選擇郁油。你可以讓你的Fragment 成為另一個Fragment component,一個Activity component或者Application component的subcomponent攀痊。它取決于你的Fragment需要綁定哪個桐腌。在決定component位置后,讓相應的類型(Activity)實現(xiàn)HasFragmentInjector苟径。比分說案站,如果你的Fragment需要綁定YourActivitySubcomponent,你的代碼會像這個樣子:

public class YourActivity extends Activity
    implements HasFragmentInjector {
  @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
    // ...
  }

  @Override
  public AndroidInjector<Fragment> fragmentInjector() {
    return fragmentInjector;
  }
}

public class YourFragment extends Fragment {
  @Inject SomeDependency someDep;

  @Override
  public void onAttach(Activity activity) {
    AndroidInjection.inject(this);
    super.onAttach(activity);
    // ...
  }
}

@Subcomponent(modules = ...)
public interface YourFragmentSubcomponent extends AndroidInjector<YourFragment> {
  @Subcomponent.Builder
  public abstract class Builder extends AndroidInjector.Builder<YourFragment> {}
}

@Module(subcomponents = YourFragmentSubcomponent.class)
abstract class YourFragmentModule {
  @Binds
  @IntoMap
  @FragmentKey(YourFragment.class)
  abstract AndroidInjector.Factory<? extends Fragment>
      bindYourFragmentInjectorFactory(YourFragmentSubcomponent.Builder builder);
}

@Subcomponent(modules = { YourFragmentModule.class, ... }
public interface YourActivityOrYourApplicationComponent { ... }

基本框架類型
Dagger2提供了DaggerActivity DaggerFragment 和 DaggerApplication這些基本框架類型棘街,實現(xiàn)了HasActivityInjector/HasFragment以及調(diào)用AndroidInjection.inject().
以下類型也包括在內(nèi):

注意: DaggerBroadcastReceiver只能在 BroadcastReceiver注冊時使用AndroidManifest.xml蟆盐。當 BroadcastReceiver在你自己的代碼中創(chuàng)建時,更喜歡構造器注入蹬碧。

支持庫

對于Android支持庫的用戶舱禽,dagger.android.support包中存在并行類型 炒刁。請注意恩沽,盡管支持Fragment用戶必須綁定AndroidInjector.Factory<? extends android.support.v4.app.Fragment>,但AppCompat用戶應繼續(xù)執(zhí)行翔始,AndroidInjector.Factory<? extends Activity>而不是<? extends AppCompatActivity>(或FragmentActivity)罗心。

何時注射

只要有可能里伯,構造方法注入是首選,因為它javac確保在設置之前沒有引用字段渤闷,這有助于避免NullPointerExceptions疾瓮。當需要成員注射(如上所述)時,傾向于盡早注射飒箭。為此狼电,DaggerActivity 呼吁AndroidInjection.inject()立即onCreate(),調(diào)用之前 super.onCreate()DaggerFragment做同樣的onAttach()弦蹂,這也防止了矛盾肩碟,如果Fragment重新連接。

AndroidInjection.inject()在之前調(diào)用是非常重要super.onCreate()Activity凸椿,因為調(diào)用在配置更改期間從先前的活動實例中super附加Fragments削祈,而這又會注入 Fragments。為了使Fragment注射成功脑漫,Activity 必須已經(jīng)注射髓抑。對于ErrorProne的用戶來說,調(diào)用AndroidInjection.inject()之后會出現(xiàn)編譯器錯誤super.onCreate()优幸。

以上內(nèi)容來自dagger2官網(wǎng)中的詳解介紹吨拍。
更具體的參考了google的官方demo后,有了這么幾個小結劈伴。
1.讓Activity密末、Fragment和Application繼承Dagger2提供的基本類型可以省去步驟4和5
2.由于Activity和Fragment在實現(xiàn)注入的時候,子組件及其構建器沒有其他方法或supertypes跛璧,因此都可以使用Pro-tips中的方法自動生成代碼严里。
3.在定制的Application中重寫了applicationInjector()方法,該方法告訴Dagger如何制造我們的@Singleton Component追城。
4.為了進一步解耦刹碾,activity之間傳值的時候,傳值activity不用改座柱,接收值的方法在接收activity的module中聲明迷帜。Activity中接收值的變量需要用@Inject注釋。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末色洞,一起剝皮案震驚了整個濱河市戏锹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌火诸,老刑警劉巖锦针,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡奈搜,警方通過查閱死者的電腦和手機悉盆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馋吗,“玉大人焕盟,你說我怎么就攤上這事『暝粒” “怎么了脚翘?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長绍哎。 經(jīng)常有香客問我堰怨,道長,這世上最難降的妖魔是什么蛇摸? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任备图,我火速辦了婚禮,結果婚禮上赶袄,老公的妹妹穿的比我還像新娘揽涮。我一直安慰自己,他們只是感情好饿肺,可當我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布蒋困。 她就那樣靜靜地躺著,像睡著了一般敬辣。 火紅的嫁衣襯著肌膚如雪雪标。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天溉跃,我揣著相機與錄音村刨,去河邊找鬼。 笑死撰茎,一個胖子當著我的面吹牛嵌牺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播龄糊,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逆粹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了炫惩?” 一聲冷哼從身側(cè)響起僻弹,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎他嚷,沒想到半個月后蹋绽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搔扁,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年蟋字,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扭勉。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡鹊奖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涂炎,到底是詐尸還是另有隱情忠聚,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布唱捣,位于F島的核電站两蟀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏震缭。R本人自食惡果不足惜赂毯,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拣宰。 院中可真熱鬧党涕,春花似錦、人聲如沸巡社。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晌该。三九已至肥荔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間朝群,已是汗流浹背燕耿。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姜胖,地道東北人缸棵。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像谭期,于是被迫代替她去往敵國和親堵第。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,654評論 2 354

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