1,概述
在Dagger 2官方文檔中,有這么一句話“A fast dependency injector for Android and Java.”,翻譯過來的意思就是:適用于Android和Java的快速依賴注入。

Gradle配置
dependencies {
implementation 'com.google.dagger:dagger:2.16'
kapt 'com.google.dagger:dagger-compiler:2.16'
}
2,注入方式(構(gòu)造方式注入和module注入)
- 采用構(gòu)造方法注入,構(gòu)造方法上加@Inject,并定義帶有@Component注解的接口
在Dagger 2中,使用javax.inject.Inject注解來標(biāo)識需要依賴注入的構(gòu)造函數(shù)和字段,以滿足Dagger構(gòu)造應(yīng)用應(yīng)用程序類的實(shí)例并滿足其依賴性。
@Inject有兩項(xiàng)職責(zé):
注解構(gòu)造函數(shù):通過標(biāo)記構(gòu)造函數(shù),告訴Dagger 2可以創(chuàng)建該類的實(shí)例(Dagger2通過Inject標(biāo)記可以在需要這個類實(shí)例的時候來找到這個構(gòu)造函數(shù)并把相關(guān)實(shí)例new出來)從而提供依賴關(guān)系。
使用@Component作為依賴注入橋梁,@Component一般用來注解接口,被注解的接口在編譯時會產(chǎn)生相應(yīng)的實(shí)例,作為提供依賴和所需依賴之間的橋梁,把相關(guān)依賴注入到其中
class StudentBean @Inject constructor(){
var num: Int = 1
var name: String = "趙四"
}
class TeacherBean @Inject constructor(var studentBean: StudentBean)
@Component
interface MainCompoment {
fun inject(test1Activity: Test1Activity)
}
/**
* 構(gòu)造方式注入
*/
class Test1Activity : AppCompatActivity() {
@Inject
internal lateinit var studentBean: StudentBean
@Inject
internal lateinit var teacherBean: TeacherBean
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activityt_test1)
DaggerMainCompoment.create().inject(this)
text.text = "學(xué)生: " + studentBean.name + studentBean.num
text2.text = "老師: " + teacherBean.studentBean.name + teacherBean.studentBean.num
}
}
運(yùn)行之后如下:

看下變成生成的代碼:
public final class DaggerMainCompoment implements MainCompoment {
private DaggerMainCompoment(Builder builder) {}
public static Builder builder() {
return new Builder();
}
public static MainCompoment create() {
return new Builder().build();
}
private TeacherBean getTeacherBean() {
return new TeacherBean(new StudentBean());
}
@Override
public void inject(Test1Activity test1Activity) {
injectTest1Activity(test1Activity);
}
//injectStudentBean方法將StudentBean和TeacherBean注入到了Test1Activity中
private Test1Activity injectTest1Activity(Test1Activity instance) {
Test1Activity_MembersInjector.injectStudentBean(instance, new StudentBean());
Test1Activity_MembersInjector.injectTeacherBean(instance, getTeacherBean());
return instance;
}
public static final class Builder {
private Builder() {}
public MainCompoment build() {
return new DaggerMainCompoment(this);
}
}
}
public final class Test1Activity_MembersInjector implements MembersInjector<Test1Activity> {
private final Provider<StudentBean> studentBeanProvider;
private final Provider<TeacherBean> teacherBeanProvider;
public Test1Activity_MembersInjector(
Provider<StudentBean> studentBeanProvider, Provider<TeacherBean> teacherBeanProvider) {
this.studentBeanProvider = studentBeanProvider;
this.teacherBeanProvider = teacherBeanProvider;
}
public static MembersInjector<Test1Activity> create(
Provider<StudentBean> studentBeanProvider, Provider<TeacherBean> teacherBeanProvider) {
return new Test1Activity_MembersInjector(studentBeanProvider, teacherBeanProvider);
}
@Override
public void injectMembers(Test1Activity instance) {
injectStudentBean(instance, studentBeanProvider.get());
injectTeacherBean(instance, teacherBeanProvider.get());
}
public static void injectStudentBean(Test1Activity instance, StudentBean studentBean) {
instance.studentBean = studentBean;
}
public static void injectTeacherBean(Test1Activity instance, TeacherBean teacherBean) {
instance.teacherBean = teacherBean;
}
}
2,采用@module,通過@provide注解提供依賴
對于module的解釋是注解的類為Dagger提供依賴關(guān)系。
之前已經(jīng)提到了,@Inject可以提供依賴關(guān)系,但是其不是萬能的。如果我們所需要的提供的構(gòu)造函數(shù)沒有使用@Inject注解,那么Module類可以在不修改構(gòu)造函數(shù)的情況下,通過provide提供依賴關(guān)系。即使是可以用@Inject注解的,依然可以通過Module提供依賴關(guān)系。
這里,我們需要明確的一個概念是@Module注解的類,是向Dagger提供依賴關(guān)系
- 定義module類,通過provide提供實(shí)例
@Module
class MainModule {
@Provides
fun provideStudentBean(): StudentBean = StudentBean()
@Provides
fun provideTeacherBean(studentBean: StudentBean): TeacherBean = TeacherBean(studentBean)
}
- 這里因?yàn)槭褂胢odule,Activity中Component注入的方式有所改變,需要使用DaggerMainCompoment中Builder提供module并創(chuàng)建,如下
/**
* 通過module進(jìn)行注入
*/
class Test2Activity : AppCompatActivity() {
@Inject
internal lateinit var studentBean: StudentBean
@Inject
internal lateinit var teacherBean: TeacherBean
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activityt_test2)
DaggerMainCompoment.builder()
.mainModule(MainModule())
.build()
.inject(this)
text.text = "學(xué)生: " + studentBean.name + studentBean.num
text2.text = "老師: " + teacherBean.studentBean.name + teacherBean.studentBean.num
}
}
最終結(jié)果展示如下

- 那么我們來看看編譯生成的代碼,DaggerMainCompoment增加了injectTest2Activity的代碼,如下
private Test2Activity injectTest2Activity(Test2Activity instance) {
Test2Activity_MembersInjector.injectStudentBean(
instance, MainModule_ProvideStudentBeanFactory.proxyProvideStudentBean(mainModule));
Test2Activity_MembersInjector.injectTeacherBean(instance, getTeacherBean());
return instance;
}
public static final class Builder {
private MainModule mainModule;
private Builder() {}
public MainCompoment build() {
if (mainModule == null) {
this.mainModule = new MainModule();
}
return new DaggerMainCompoment(this);
}
public Builder mainModule(MainModule mainModule) {
this.mainModule = Preconditions.checkNotNull(mainModule);
return this;
}
}
通過創(chuàng)建Builder,提供了mainModule的實(shí)例,并傳到MainCompoment
Test2Activity_MembersInjector.injectStudentBean(
instance, MainModule_ProvideStudentBeanFactory.proxyProvideStudentBean(mainModule));
通過proxyProvideStudentBean方法獲取StudentBean實(shí)例,代碼如下:
public static StudentBean proxyProvideStudentBean(MainModule instance) {
return Preconditions.checkNotNull(
instance.provideStudentBean(), "Cannot return null from a non-@Nullable @Provides method");
}
通過MainModule.取到了該類中提供的StudentBean實(shí)例,最后一步往下看
public static void injectStudentBean(Test2Activity instance, StudentBean studentBean) {
instance.studentBean = studentBean;
}
injectStudentBean方法將獲取到的studentBean賦值給了Test2Activity
- 再來看一下顯示提供依賴的實(shí)現(xiàn),增加provideStudentBean方法
@Component(modules = [MainModule::class])
interface MainCompoment {
fun inject(test1Activity: Test1Activity)
fun inject(test2Activity: Test2Activity)
fun provideStudentBean(): StudentBean
}
如下調(diào)用
val build = DaggerMainCompoment.builder()
.mainModule(MainModule())
.build()
build.inject(this)
val provideStudentBean = build.provideStudentBean()
Log.e("test2", provideStudentBean.name + provideStudentBean.num)
此方法provideStudentBean,最終會在DaggerMainCompoment進(jìn)行實(shí)現(xiàn),最終還是調(diào)用到MainModule中提供的實(shí)例
@Override
public StudentBean provideStudentBean() {
return MainModule_ProvideStudentBeanFactory.proxyProvideStudentBean(mainModule);
}
public static StudentBean proxyProvideStudentBean(MainModule instance) {
return Preconditions.checkNotNull(
instance.provideStudentBean(), "Cannot return null from a non-@Nullable @Provides method");
}
此前生成的bean生成的代碼還一直未使用如下,先放著
public final class StudentBean_Factory implements Factory<StudentBean> {
private static final StudentBean_Factory INSTANCE = new StudentBean_Factory();
@Override
public StudentBean get() {
return provideInstance();
}
public static StudentBean provideInstance() {
return new StudentBean();
}
public static StudentBean_Factory create() {
return INSTANCE;
}
public static StudentBean newStudentBean() {
return new StudentBean();
}
}
3, @Qualifier限定符
- 提供相同返回值的依賴,會造成Dagger的“依賴迷失”,無法確定提供哪個依賴
可通過自定義注解進(jìn)行區(qū)分,如下不做詳解
@Module()
public class FruitModule {
//使用限定符來區(qū)別使用哪個構(gòu)造函數(shù)返回對象
@Type("color")
@Provides
public AppleBean provideColorApple() {
return new AppleBean("red");
}
@Type("name")
@Provides
public AppleBean provideNameApple() {
return new AppleBean("紅富士", 6.88);
}
}
4,@Scope作用域
作用域的理解是變量的作用范圍,因此,出現(xiàn)了全局變量和局部變量之分
同vue中css使用scope,表示css只在當(dāng)前頁面生效;所以scope如同設(shè)定提供依賴的聲明周期一樣.如定義的@AppScope在App進(jìn)行build,最終生命周期是整個app,如定義的@ActivityScope是在Activity中build,那么生命周期同activity
如果使用了@Scope注解了該類,注入器會緩存第一次創(chuàng)建的實(shí)例,然后每次重復(fù)注入緩存的實(shí)例,而不會再創(chuàng)建新的實(shí)例
接下來結(jié)合代碼實(shí)例講解,只有BoysBean添加@ActivityScope
(如果MainCompoment中module有使用scope,則Component需要有該scope)
@Provides
fun provideGirlsBean(): GirlsBean = GirlsBean()
@ActivityScope
@Provides
fun provideBoysBean(): BoysBean = BoysBean()
@Inject
internal lateinit var boysBean: BoysBean
@Inject
internal lateinit var boysBean2: BoysBean
@Inject
internal lateinit var girlsBean: GirlsBean
@Inject
internal lateinit var girlsBean2: GirlsBean
Log.e("test2", "girlsBean " + girlsBean.toString())
Log.e("test2", "girlsBean2 " + girlsBean2.toString())
Log.e("test2", "boysBean " + boysBean.toString())
Log.e("test2", "boysBean2 " + boysBean2.toString())
2018-08-20 21:19:49.388 2417-2417/com.plugin.gradle.lucio.dagger2 E/test2: girlsBean com.plugin.gradle.lucio.dagger2.domain.GirlsBean@c287b9a
2018-08-20 21:19:49.388 2417-2417/com.plugin.gradle.lucio.dagger2 E/test2: girlsBean2 com.plugin.gradle.lucio.dagger2.domain.GirlsBean@601bccb
2018-08-20 21:19:49.388 2417-2417/com.plugin.gradle.lucio.dagger2 E/test2: boysBean com.plugin.gradle.lucio.dagger2.domain.BoysBean@6456ca8
2018-08-20 21:19:49.388 2417-2417/com.plugin.gradle.lucio.dagger2 E/test2: boysBean2 com.plugin.gradle.lucio.dagger2.domain.BoysBean@6456ca8
可見帶@ActivityScope的bean進(jìn)行緩存了,我們來看看DaggerMainCompoment生成的代碼的區(qū)別
private void initialize(final Builder builder) {
this.mainModule = builder.mainModule;
this.provideBoysBeanProvider =
DoubleCheck.provider(MainModule_ProvideBoysBeanFactory.create(builder.mainModule));
}
由BoysBean類生成的factory代碼開始使用,通過create創(chuàng)建了MainModule_ProvideBoysBeanFactory,并通過get()提供BoysBean實(shí)例
@Override
public BoysBean get() {
return provideInstance(module);
}
public static MainModule_ProvideBoysBeanFactory create(MainModule module) {
return new MainModule_ProvideBoysBeanFactory(module);
}
同時使用DoubleCheck.provider保持bean的單例
public static <P extends Provider<T>, T> Provider<T> provider(P delegate) {
checkNotNull(delegate);
if (delegate instanceof DoubleCheck) {
/* This should be a rare case, but if we have a scoped @Binds that delegates to a scoped
* binding, we shouldn't cache the value again. */
return delegate;
}
return new DoubleCheck<T>(delegate);
}
最后看看兩者bean的區(qū)別
private Test2Activity injectTest2Activity(Test2Activity instance) {
Test2Activity_MembersInjector.injectStudentBean(
instance, MainModule_ProvideStudentBeanFactory.proxyProvideStudentBean(mainModule));
Test2Activity_MembersInjector.injectTeacherBean(instance, getTeacherBean());
Test2Activity_MembersInjector.injectBoysBean(instance, provideBoysBeanProvider.get());
Test2Activity_MembersInjector.injectBoysBean2(instance, provideBoysBeanProvider.get());
Test2Activity_MembersInjector.injectGirlsBean(
instance, MainModule_ProvideGirlsBeanFactory.proxyProvideGirlsBean(mainModule));
Test2Activity_MembersInjector.injectGirlsBean2(
instance, MainModule_ProvideGirlsBeanFactory.proxyProvideGirlsBean(mainModule));
return instance;
}
BoysBean通過provideBoysBeanProvider.get()獲取,GirlsBean通過 MainModule_ProvideGirlsBeanFactory.proxyProvideGirlsBean(mainModule)重新創(chuàng)建,由此可見BoysBean的實(shí)例隨activity生命周期
5,多個元素綁定并注入到Set
將多個元素注入到Set中,不僅支持單個元素注入到Set中,同時支持子Set<T>注入到Set中。
@Module()
public class FruitModule {
@Provides
@IntoSet
public BananaBean providerBanana() {
return new BananaBean("特朗普香蕉");
}
}
@Module()
public class DrinkModule {
@Provides
@IntoSet
public BananaBean providerBanana() {
return new BananaBean("巴拿馬香蕉");
}
將子Set<T>注入到Set:
@Module()
public class FruitModule {
@Provides
@ElementsIntoSet
public Set<BananaBean> providerBananaSet() {
Set<BananaBean> set = new HashSet<>();
set.add(new BananaBean("布什香蕉"));
set.add(new BananaBean("約翰遜香蕉"));
return set;
}
}
class Test3Activity : AppCompatActivity() {
@Inject
internal lateinit var studentBean: Set<BananaBean>
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activityt_test3)
DaggerMainCompoment.create().inject(this)
val stringBuilder1 = StringBuilder()
studentBean.forEach {
stringBuilder1.append(it.name + " ")
}
text.text = stringBuilder1
}
}
生成代碼同上,不做分析,測試結(jié)果如下

5,多個元素綁定并注入到Map
Dagger不僅可以將綁定的多個元素依賴注入到Set,還可以將綁定的多個元素依賴注入到Map。與依賴注入Set不同的是,依賴注入Map時,必須在編譯時指定Map的Key,那么Dagger向MapMap注入相應(yīng)的元素。
對于向Map提供元素的@Provides方法,需要使用@IntoMap,同時指定該元素的Key(例如@StringKey(“foo”)、@ClassKey(Thing.class))。
- 我們先以StringKey、ClassKey注解為例注入Map:
@Provides
@IntoMap // 指定該@Provides方法向Map提供元素
@StringKey("A") // 指定該元素在Map中所對應(yīng)的的Key
fun providerApple(): AppleBean = AppleBean("A蘋果")
@Provides
@IntoMap
@ClassKey(Test3Activity::class)
fun providerAppleMap(): AppleBean = AppleBean("北京蘋果")
- 獲取依賴
class Test3Activity : AppCompatActivity() {
@Inject
internal lateinit var studentBean: Set<BananaBean>
@Inject
internal lateinit var appleBean: Map<String, AppleBean>
@Inject
internal lateinit var appleBean2: Map<Class<*>, AppleBean>
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activityt_test3)
DaggerMainCompoment.create().inject(this)
val stringBuilder1 = StringBuilder()
val stringBuilder2 = StringBuilder()
val stringBuilder3 = StringBuilder()
studentBean.forEach {
stringBuilder1.append(it.name + " ")
}
appleBean.forEach {
stringBuilder2.append(it.value.name + " ")
}
appleBean2.forEach {
stringBuilder3.append(it.value.name + " ")
}
text.text = stringBuilder1
text2.text = stringBuilder2
text3.text = stringBuilder3
}
}
結(jié)果如下:

6,自定義Key
在注釋類型中聲明的方法的返回類型,如果不滿足指定的返回類型,那么編譯時會報(bào)錯:
基本數(shù)據(jù)類型
String
Class
枚舉類型
注解類型
以上數(shù)據(jù)類型的數(shù)組
@MapKey
public @interface MyNumberClassKey {
Class<? extends Number> value();
}
@Provides
@IntoMap
@MyNumberClassKey(BigDecimal::class)
fun provideBigDecimalValue(): String = "value for BigDecimal"
@Inject
internal lateinit var enum2: Map<Class<out Number>, String>
enum2.forEach { stringBuilder5.append(it.value) }
text5.text = stringBuilder5
結(jié)果如下

7,Component依賴關(guān)系
在使用Dagger 2開發(fā)時,一般都是在Application中生成一個AppComponent,然后其他的功能模塊的Component依賴于AppComponent,作為AppComponent的子組件。可是,對于將自組建添加到父組件有兩種方式:
- 通過@Component的dependencies屬性依賴父組件
@Component(modules = OrangeModule.class, dependencies = FruitComponent.class)
public interface OrangeComponent {}
- 通過Moudle的subcomponents屬性添加子組件
@Module(subcomponents = AppleSubcomponent.class)
public class FruitModule {}
Subcomponents(子組件)和組件依賴最大的不同是當(dāng)你接入父組件的時候,你可以訪問它所有模塊的所有對象而無需顯示聲明依賴父組件,而組件依賴必須顯示提供依賴,后面做詳解
- Subcomponent的介紹
對于繼承,大家應(yīng)該都不陌生,其實(shí)就是子類繼承父類,子類自動獲取了的父類的屬性和行為。我覺得我們也可以這么認(rèn)為子組件。子組件是繼承和擴(kuò)展父組件的對象的組件
- 添加子組件
聲明子組件,與普通組件聲明類似,可以通過編寫一個抽象類或接口來創(chuàng)建一個子組件,該類或接口聲明了返回應(yīng)用程序相關(guān)的類型的抽象方法??梢允褂聾Component,也可以使用@Subcomponent注解,這個沒有一定的強(qiáng)制性。
與@Component注解不同的是,使用@Subcomponent注解子組件,必須聲明其xxComponent.Builder,否則編譯時,會報(bào)錯。
@Subcomponent(modules = AppleModule.class)
public interface AppleSubcomponent {
AppleBean supplyApple();
@Subcomponent.Builder
interface Builder{
Builder appleModule(AppleModule module);
AppleSubcomponent build();
}
}
通過@Component的dependencies屬性依賴父組件
注意:
子類的作用域和父類的不能一樣,要不然會報(bào)以下錯誤
SecondComponent depends on scoped components in a non-hierarchical scope ordering:
依賴Component(OrangeComponent) 僅繼承 被依賴Component(FruitComponent) 中顯示提供的依賴。如果被依賴Component(FruitComponent)必須提供依賴注入的對象,也就是將對象實(shí)例暴露出來。否則,在子組件,也就是依賴Component(OrangeComponent)中,無法使用@Inject注入被依賴的Component(AppComponent)中的對象,此時編譯器會報(bào)錯,提示依賴注入的Xx實(shí)例沒有提供@Inject注解或者@Provides方法。
@SubScope
@Component(dependencies = [MainCompoment::class])
interface DeComponent {
fun inject(test4Activity: Test4Activity)
}
class Test4Activity : AppCompatActivity() {
@Inject
internal lateinit var studentBean: StudentBean
@Inject
internal lateinit var girlsBean: GirlsBean
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activityt_test4)
DaggerDeComponent.builder()
.mainCompoment(DaggerMainCompoment.create())
.build()
.inject(this)
text.text = studentBean.name
text2.text = girlsBean.name
}
}
結(jié)果如下

我們來看一下DaggerDeComponent中生成的代碼
- 首先initialize中獲取了mainCompoment
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainCompoment = builder.mainCompoment;
}
- 這里通過provideStudentBean方法直接取到了顯示提供的依賴,最后注入到Test4Activity
private Test4Activity injectTest4Activity(Test4Activity instance) {
Test4Activity_MembersInjector.injectStudentBean(
instance,
Preconditions.checkNotNull(
mainCompoment.provideStudentBean(),
"Cannot return null from a non-@Nullable component method"));
Test4Activity_MembersInjector.injectGirlsBean(
instance,
Preconditions.checkNotNull(
mainCompoment.provideGirlsBean(),
"Cannot return null from a non-@Nullable component method"));
return instance;
}
- 測試一下不顯示的提供依賴會有什么結(jié)果, 編譯時DeComponent會報(bào)錯
/Users/lucio/Documents/third_frame/dagger2/app/build/tmp/kapt3/stubs/debug/com/plugin/gradle/lucio/dagger2/di/component/DeComponent.java:17: error: [Dagger/MissingBinding] com.plugin.gradle.lucio.dagger2.domain.GirlsBean cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract void inject(@org.jetbrains.annotations.NotNull()
^
com.plugin.gradle.lucio.dagger2.domain.GirlsBean is injected at
com.plugin.gradle.lucio.dagger2.ui.Test4Activity.girlsBean
com.plugin.gradle.lucio.dagger2.ui.Test4Activity is injected at
com.plugin.gradle.lucio.dagger2.di.component.DeComponent.inject(com.plugin.gradle.lucio.dagger2.ui.Test4Activity)
通過Moudle的subcomponents屬性添加子組件
@SubComponent的寫法與@Component一樣,只能標(biāo)注接口或抽象類,與依賴關(guān)系一樣,SubComponent 與 parent Component 的 Scope 不能相同,只是 SubComponent 表明它是繼承擴(kuò)展某 Component 的。怎么表明一個 SubComponent 是屬于哪個 parent Component 的呢?只需要在 parent Component 依賴的 Module 中的subcomponents加上 SubComponent 的 class,然后就可以在 parent Component 中請求 SubComponent.Builder。
@Subcomponent(modules = [AppleModule::class])
interface SonComponent {
fun inject(test5Activity: Test5Activity)
@Subcomponent.Builder
interface Builder {
fun appleModule(module: AppleModule): Builder
fun build(): SonComponent
}
}
MainModule添加SonComponent的subcomponents
@Module(subcomponents = [SonComponent::class])
class MainModule {
@Provides
fun provideStudentBean(): StudentBean = StudentBean()
@Provides
fun provideTeacherBean(studentBean: StudentBean): TeacherBean = TeacherBean(studentBean)
@Provides
fun provideGirlsBean(): GirlsBean = GirlsBean()
@ActivityScope
@Provides
fun provideBoysBean(): BoysBean = BoysBean()
}
MainCompoment中添加fun sonComponent(): SonComponent.Builder
@ActivityScope
@Component(modules = [MainModule::class, DrinkModule::class, FruitModule::class, CusMapKeyModule::class])
interface MainCompoment {
fun inject(test1Activity: Test1Activity)
fun inject(test2Activity: Test2Activity)
fun inject(test3Activity: Test3Activity)
fun provideStudentBean(): StudentBean
fun provideGirlsBean(): GirlsBean
fun sonComponent(): SonComponent.Builder // 用來創(chuàng)建 Subcomponent
}
- 我們先獲取MainModule中StudentBean和TeacherBean
class Test5Activity : AppCompatActivity() {
@Inject
internal lateinit var studentBean: StudentBean
@Inject
internal lateinit var teacherBean: TeacherBean
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activityt_test1)
DaggerMainCompoment.create()
.sonComponent()
.build()
.inject(this)
text.text = "學(xué)生: " + studentBean.name + studentBean.num
text2.text = "老師: " + teacherBean.studentBean.name + teacherBean.studentBean.num
}
}
結(jié)果如下

我們來看一下生成的代碼,如果取到parent Component的依賴
- 首先通過sonComponent創(chuàng)建SonComponentBuilder
@Override
public SonComponent.Builder sonComponent() {
return new SonComponentBuilder();
}
- 通過SonComponentBuilder中build創(chuàng)建SonComponentImpl,再調(diào)用inject方法,
到這里我們就發(fā)現(xiàn), SonComponentImpl是MainComponent的內(nèi)部類,自然可以獲取到外部類MainComponent的mainModule和getTeacherBean()方法,通過mainModule則獲取到StudentBean,getTeacherBean()獲取到TeacherBean,
Test5Activity_MembersInjector. injectStudentBean()和injectTeacherBean()則注入到Test5Activity
private final class SonComponentBuilder implements SonComponent.Builder {
@Override
public SonComponent build() {
return new SonComponentImpl(this);
}
/**
* This module is declared, but an instance is not used in the component. This method is a
* no-op. For more, see https://google.github.io/dagger/unused-modules.
*/
@Override
public SonComponentBuilder appleModule(AppleModule module) {
return this;
}
}
private final class SonComponentImpl implements SonComponent {
private SonComponentImpl(SonComponentBuilder builder) {}
@Override
public void inject(Test5Activity test5Activity) {
injectTest5Activity(test5Activity);
}
private Test5Activity injectTest5Activity(Test5Activity instance) {
Test5Activity_MembersInjector.injectStudentBean(
instance,
MainModule_ProvideStudentBeanFactory.proxyProvideStudentBean(
DaggerMainCompoment.this.mainModule));
Test5Activity_MembersInjector.injectTeacherBean(
instance, DaggerMainCompoment.this.getTeacherBean());
return instance;
}
}
}
再看看獲取AppleModule中的依賴
@Inject
internal lateinit var studentBean: StudentBean
text3.text = "apple: " + appleBean.name
結(jié)果如下

看看生成的代碼, build中創(chuàng)建了AppleModule, injectAppleBean則進(jìn)行了注入
@Override
public SonComponent build() {
if (appleModule == null) {
this.appleModule = new AppleModule();
}
return new SonComponentImpl(this);
}
Test5Activity_MembersInjector.injectAppleBean(
instance, AppleModule_PrivdeAppleFactory.proxyPrivdeApple(appleModule));
8,完美擴(kuò)展庫-dagger.android
- Dagger的使用流程
1,在ApplicationComponent中注入AndroidInjectionModule,如果項(xiàng)目中用到v4包的Fragment,還需注入AndroidSupportInjectionModule.建議把兩個Module都注入XxComponent中
@Component(modules = [
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class])
interface AppComponent {
fun inject(instance: App?)
}
2,創(chuàng)建子組件 - @Subcomponent,其繼承自AndroidInjector<T>,而T就是step2創(chuàng)建的Android庫的類型
@Subcomponent(modules = [MainModule::class]) //這里需要MainModule,否則會關(guān)聯(lián)不上
interface SonComponent : AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainActivity>()
}
3,創(chuàng)建Module,其subcomponents屬性值就是step3創(chuàng)建的子組件。在其內(nèi)必須聲明一個抽象方法,該抽象方法返回AndroidInjector.Factory<?>實(shí)例,而其參數(shù)為step1創(chuàng)建的XxSubcomponent.Builder實(shí)例。
@Module(subcomponents = [SonComponent::class])
abstract class ActivityBuilder {
@Binds
@IntoMap
@ActivityKey(MainActivity::class)
internal abstract fun bindYourActivityInjectorFactory(builder: SonComponent.Builder): AndroidInjector.Factory<out Activity>
}
4,將創(chuàng)建的Module注入到ApplicationComponent中,即把其添加至ApplicationComponent的modules屬性列表,即添加ActivityBuilder
@Component(modules = [
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
ActivityBuilder::class])
interface AppComponent {
fun inject(instance: App?)
}
5,創(chuàng)建Application。實(shí)現(xiàn)HasActivityInjector, HasSupportFragmentInjector支持activity和fragment的注解。
class App : Application(), HasActivityInjector, HasSupportFragmentInjector {
//依賴注入的核心原則:一個類不應(yīng)該知道如何實(shí)現(xiàn)依賴注入。
@Inject
internal lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
@Inject
internal lateinit var fragmentSupportInjector: DispatchingAndroidInjector<Fragment>
override fun onCreate() {
super.onCreate()
DaggerAppComponent.create().inject(this)
}
override fun activityInjector(): AndroidInjector<Activity>? = dispatchingAndroidInjector
override fun supportFragmentInjector(): AndroidInjector<Fragment> = fragmentSupportInjector
}
6,添加module提供依賴
@Module
class MainModule {
@Provides
fun providesBoysBean(): BoysBean = BoysBean()
}
@Subcomponent(modules = [MainModule::class]) //這里需要MainModule,否則會關(guān)聯(lián)不上
interface SonComponent : AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainActivity>()
}
7,創(chuàng)建Android庫的核心類,需要注意的就是:AndroidInjection.inject(T)方法的調(diào)用位置,即可展示出來
class MainActivity : AppCompatActivity() {
@Inject
internal lateinit var boysBean: BoysBean
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
text.text = boysBean.name
}
}
我們來看一下生成的DaggerAppComponent
// Generated by Dagger (https://google.github.io/dagger).
package com.plugin.gradle.lucio.dagger_android.di.component;
import android.app.Activity;
import androidx.fragment.app.Fragment;
import com.plugin.gradle.lucio.dagger_android.App;
import com.plugin.gradle.lucio.dagger_android.App_MembersInjector;
import com.plugin.gradle.lucio.dagger_android.MainActivity;
import com.plugin.gradle.lucio.dagger_android.MainActivity_MembersInjector;
import com.plugin.gradle.lucio.dagger_android.di.module.MainModule;
import com.plugin.gradle.lucio.dagger_android.di.module.MainModule_ProvidesBoysBeanFactory;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.DispatchingAndroidInjector_Factory;
import dagger.internal.Preconditions;
import java.util.Collections;
import java.util.Map;
import javax.inject.Provider;
public final class DaggerAppComponent implements AppComponent {
private Provider<SonComponent.Builder> sonComponentBuilderProvider;
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static AppComponent create() {
return new Builder().build();
}
private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
getMapOfClassOfAndProviderOfFactoryOf() {
return Collections
.<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
singletonMap(MainActivity.class, (Provider) sonComponentBuilderProvider);
}
private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
getMapOfClassOfAndProviderOfFactoryOf());
}
private DispatchingAndroidInjector<Fragment> getDispatchingAndroidInjectorOfFragment() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
Collections
.<Class<? extends Fragment>, Provider<AndroidInjector.Factory<? extends Fragment>>>
emptyMap());
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.sonComponentBuilderProvider =
new Provider<SonComponent.Builder>() {
@Override
public SonComponent.Builder get() {
return new SonComponentBuilder();
}
};
}
@Override
public void inject(App instance) {
injectApp(instance);
}
private App injectApp(App instance) {
App_MembersInjector.injectDispatchingAndroidInjector(
instance, getDispatchingAndroidInjectorOfActivity());
App_MembersInjector.injectFragmentSupportInjector(
instance, getDispatchingAndroidInjectorOfFragment());
return instance;
}
public static final class Builder {
private Builder() {}
public AppComponent build() {
return new DaggerAppComponent(this);
}
}
private final class SonComponentBuilder extends SonComponent.Builder {
private MainModule mainModule;
private MainActivity seedInstance;
@Override
public SonComponent build() {
if (mainModule == null) {
this.mainModule = new MainModule();
}
if (seedInstance == null) {
throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
}
return new SonComponentImpl(this);
}
@Override
public void seedInstance(MainActivity arg0) {
this.seedInstance = Preconditions.checkNotNull(arg0);
}
}
private final class SonComponentImpl implements SonComponent {
private MainModule mainModule;
private SonComponentImpl(SonComponentBuilder builder) {
initialize(builder);
}
@SuppressWarnings("unchecked")
private void initialize(final SonComponentBuilder builder) {
this.mainModule = builder.mainModule;
}
@Override
public void inject(MainActivity arg0) {
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectBoysBean(
instance, MainModule_ProvidesBoysBeanFactory.proxyProvidesBoysBean(mainModule));
return instance;
}
}
}
initialize()方法初始化時創(chuàng)建了內(nèi)部類SonComponentBuilder,提供了MainModule并創(chuàng)建SonComponentImpl內(nèi)部類,來看下SonComponentImpl
private final class SonComponentImpl implements SonComponent {
private MainModule mainModule;
private SonComponentImpl(SonComponentBuilder builder) {
initialize(builder);
}
@SuppressWarnings("unchecked")
private void initialize(final SonComponentBuilder builder) {
this.mainModule = builder.mainModule;
}
@Override
public void inject(MainActivity arg0) {
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectBoysBean(
instance, MainModule_ProvidesBoysBeanFactory.proxyProvidesBoysBean(mainModule));
return instance;
}
}
SonComponentImpl實(shí)現(xiàn)了SonComponent,而SonComponent實(shí)現(xiàn)了AndroidInjector<T>并傳入activity,再看看AndroidInjector<T>中的 inject(T instance);什么時候調(diào)用
@Beta
public interface AndroidInjector<T> {
/** Injects the members of {@code instance}. */
void inject(T instance);
/**
* Creates {@link AndroidInjector}s for a concrete subtype of a core Android type.
*
* @param <T> the concrete type to be injected
*/
interface Factory<T> {
/**
* Creates an {@link AndroidInjector} for {@code instance}. This should be the same instance
* that will be passed to {@link #inject(Object)}.
*/
AndroidInjector<T> create(T instance);
}
/**
* An adapter that lets the common {@link dagger.Subcomponent.Builder} pattern implement {@link
* Factory}.
*
* @param <T> the concrete type to be injected
*/
abstract class Builder<T> implements AndroidInjector.Factory<T> {
@Override
public final AndroidInjector<T> create(T instance) {
seedInstance(instance);
return build();
}
/**
* Provides {@code instance} to be used in the binding graph of the built {@link
* AndroidInjector}. By default, this is used as a {@link BindsInstance} method, but it may be
* overridden to provide any modules which need a reference to the activity.
*
* <p>This should be the same instance that will be passed to {@link #inject(Object)}.
*/
@BindsInstance
public abstract void seedInstance(T instance);
/** Returns a newly-constructed {@link AndroidInjector}. */
public abstract AndroidInjector<T> build();
}
}
我們回頭看看activity中AndroidInjection.inject(this)方法
public static void inject(Activity activity) {
checkNotNull(activity, "activity");
Application application = activity.getApplication();
if (!(application instanceof HasActivityInjector)) {
throw new RuntimeException(
String.format(
"%s does not implement %s",
application.getClass().getCanonicalName(),
HasActivityInjector.class.getCanonicalName()));
}
AndroidInjector<Activity> activityInjector =
((HasActivityInjector) application).activityInjector();
checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
activityInjector.inject(activity);
}
這里通過((HasActivityInjector) application).activityInjector();取到了AndroidInjector<Activity> ,來看一下如果取到AndroidInjector,關(guān)鍵在于DaggerAppComponent中的inject方法,調(diào)用了injectApp
private App injectApp(App instance) {
App_MembersInjector.injectDispatchingAndroidInjector(
instance, getDispatchingAndroidInjectorOfActivity());
App_MembersInjector.injectFragmentSupportInjector(
instance, getDispatchingAndroidInjectorOfFragment());
return instance;
}
看看getDispatchingAndroidInjectorOfActivity()方法,創(chuàng)建了DispatchingAndroidInjector
private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
getMapOfClassOfAndProviderOfFactoryOf());
}
public static <T> DispatchingAndroidInjector<T> newDispatchingAndroidInjector(
Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories) {
return new DispatchingAndroidInjector<T>(injectorFactories);
}
看一下 App_MembersInjector.injectDispatchingAndroidInjector(
instance, getDispatchingAndroidInjectorOfActivity());的代碼
public static void injectDispatchingAndroidInjector(
App instance, DispatchingAndroidInjector<Activity> dispatchingAndroidInjector) {
instance.dispatchingAndroidInjector = dispatchingAndroidInjector;
}
override fun activityInjector(): AndroidInjector<Activity>? = dispatchingAndroidInjector
這里將獲取到的dispatchingAndroidInjector賦值到了App中activityInjector()方法,即獲取到ActivityInjector
然后調(diào)用了activityInjector.inject(activity);方法,執(zhí)行debug會執(zhí)行DispatchingAndroidInjector類中inject方法
@Override
public void inject(T instance) {
boolean wasInjected = maybeInject(instance);
if (!wasInjected) {
throw new IllegalArgumentException(errorMessageSuggestions(instance));
}
}
@CanIgnoreReturnValue
public boolean maybeInject(T instance) {
Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
injectorFactories.get(instance.getClass());
if (factoryProvider == null) {
return false;
}
@SuppressWarnings("unchecked")
AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
try {
AndroidInjector<T> injector =
checkNotNull(
factory.create(instance), "%s.create(I) should not return null.", factory.getClass());
injector.inject(instance);
return true;
} catch (ClassCastException e) {
throw new InvalidInjectorBindingException(
String.format(
"%s does not implement AndroidInjector.Factory<%s>",
factory.getClass().getCanonicalName(), instance.getClass().getCanonicalName()),
e);
}
}
這里factory.create(instance)方法,會執(zhí)行AndroidInjector<T>中create(),接著執(zhí)行Builder中create(),執(zhí)行build()和seedInstance(),此時DaggerAppComponent中內(nèi)部類SonComponentBuilder才執(zhí)行了build(),從而創(chuàng)建SonComponentImpl
interface Factory<T> {
/**
* Creates an {@link AndroidInjector} for {@code instance}. This should be the same instance
* that will be passed to {@link #inject(Object)}.
*/
AndroidInjector<T> create(T instance);
}
abstract class Builder<T> implements AndroidInjector.Factory<T> {
@Override
public final AndroidInjector<T> create(T instance) {
seedInstance(instance);
return build();
}
/**
* Provides {@code instance} to be used in the binding graph of the built {@link
* AndroidInjector}. By default, this is used as a {@link BindsInstance} method, but it may be
* overridden to provide any modules which need a reference to the activity.
*
* <p>This should be the same instance that will be passed to {@link #inject(Object)}.
*/
@BindsInstance
public abstract void seedInstance(T instance);
/** Returns a newly-constructed {@link AndroidInjector}. */
public abstract AndroidInjector<T> build();
}
最后DispatchingAndroidInjector中的injector.inject(instance);執(zhí)行
將activity傳遞過去,所以SonComponentImpl中實(shí)現(xiàn)的inject被執(zhí)行了
@Override
public void inject(MainActivity arg0) {
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectBoysBean(
instance, MainModule_ProvidesBoysBeanFactory.proxyProvidesBoysBean(mainModule));
return instance;
}
由此將boysBean的依賴傳遞到MainAcitivity
9,簡化
采用ContributesAndroidInjector注解
//@Module(subcomponents = [SonComponent::class])
@Module()
abstract class ActivityModuleBuilder {
// @Binds
// @IntoMap
// @ActivityKey(MainActivity::class)
// internal abstract fun bindYourActivityInjectorFactory(builder: SonComponent.Builder): AndroidInjector.Factory<out Activity>
@ContributesAndroidInjector(modules = [(MainModule::class)])
internal abstract fun bindMainActivity(): MainActivity
}
來看一下采用該注解之后的變化,會生成ActivityModuleBuilder_BindMainActivity類,生成的代碼和之前使用Subcomponent形式一模一樣,不再多做講解
@Module(
subcomponents = ActivityModuleBuilder_BindMainActivity$app_debug.MainActivitySubcomponent.class
)
public abstract class ActivityModuleBuilder_BindMainActivity$app_debug {
private ActivityModuleBuilder_BindMainActivity$app_debug() {}
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory(
MainActivitySubcomponent.Builder builder);
@Subcomponent(modules = MainModule.class)
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {}
}
}