將以下內(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
確保在設置之前沒有引用字段渤闷,這有助于避免NullPointerException
s疾瓮。當需要成員注射(如上所述)時,傾向于盡早注射飒箭。為此狼电,DaggerActivity
呼吁AndroidInjection.inject()
立即onCreate()
,調(diào)用之前 super.onCreate()
和DaggerFragment
做同樣的onAttach()
弦蹂,這也防止了矛盾肩碟,如果Fragment
重新連接。
AndroidInjection.inject()
在之前調(diào)用是非常重要super.onCreate()
的Activity
凸椿,因為調(diào)用在配置更改期間從先前的活動實例中super
附加Fragment
s削祈,而這又會注入 Fragment
s。為了使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注釋。