Android--Dagger2入门

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android--Dagger2入门相关的知识,希望对你有一定的参考价值。

参考技术A

dagger拥有两种方式注入对象,一种是利用 @Inject注解 构造函数

在moudle的gradle中做如下配置,我在2.30.1版本中尝试使用构造函数注入,发现怎么编译都会报错,结果最后使用最新版本就可以了:

这边定义两个类,分别代表本地和远程的数据源,并对构造函数使用@Inject注解

定义包装类DataSource,包含上面两个类,同样对构造函数使用@Inject注解

对于需要注入的对象,dagger并不是直接注入,而是需要一个中间件去注入他们,使用代理模式的思想,这样的好处是方便管理和控制

build下项目后,dagger会对应生成一个DaggerApplicationComponent类,通过上篇文章,我们知道用的是APT技术

调用生成类DaggerApplicationComponent的注入方法

运行后日志:
2021-12-04 /com.aruba.daggerapplication I/aruba_log: DataSource(remoteDataSource=com.aruba.daggerapplication.di.datasource.RemoteDataSource@1ae5a6b, localDataSource=com.aruba.daggerapplication.di.datasource.LocalDataSource@8b49c8)

可以看到dagger帮我们自动生成注入对象了,并且我们在使用的地方不需要关注它是如何生成的

第二种方式就是模块注入,构造函数注入是以类为对象,模块注入则是以方法为对象
接下来尝试使用网络请求,以获取百度的首页html

别忘了在Manifest.xml中添加权限

效果:

模块注入同样也实现了自动注入对象,并且这种方式可读性和可维护性更高

通过上面两种方式,我们知道了如何注入对象,但是我们并不知道注入的对象的生命周期,有时我们希望获取的对象是一个单例,这种情况仅仅使用注入是无法实现的

下面例子,通过注入两个相同类型对象,查看它们是否是同一份实例
在MainActivity中同时注入两个DataSource对象,并通过打印日志,观测结果

日志打印:
2021-12-04/com.aruba.daggerapplication I/aruba_log: DataSource(remoteDataSource=com.aruba.daggerapplication.di.datasource.RemoteDataSource@137fdbe, localDataSource=com.aruba.daggerapplication.di.datasource.LocalDataSource@31b1e1f)
2021-12-04/com.aruba.daggerapplication I/aruba_log: DataSource(remoteDataSource=com.aruba.daggerapplication.di.datasource.RemoteDataSource@b3756c, localDataSource=com.aruba.daggerapplication.di.datasource.LocalDataSource@7b81735)
2021-12-04/com.aruba.daggerapplication I/aruba_log: false

结果显示这两个对象不是同一个实例

在使用构造注入或Module注入时,一旦使用了作用域注解,其Component也要使用相同的作用域注解,否则编译会报错。同一个Component实例在注入对象时,一旦发现注入方式使用了作用域,那么它们注入的对象将会是同一份实例

@Singleton注解为dagger默认提供的一个作用域注解。定义一个构造函数注入方式,并使用该注解

在Component中,使用相同作用域,并且我重新定义了一个ScopeActivity来测试结果

ScopeActivity中需要注入两个SingletonTest 对象,并打印是否为同一个实例

日志结果:
2021-12-04/com.aruba.daggerapplication I/aruba_log: singleton1 hashcode: 246939604
2021-12-04/com.aruba.daggerapplication I/aruba_log: singleton2 hashcode: 246939604

结果显示,这两个对象是同一份实例

将上面的作用域注解替换成MyScope

日志结果:
2021-12-04/com.aruba.daggerapplication I/aruba_log: singleton1 hashcode: 246939604
2021-12-04/com.aruba.daggerapplication I/aruba_log: singleton2 hashcode: 246939604

和使用@Singleton是相同的效果

模块注入方式,使用作用域注解在方法上:

即使用了同一个作用域,不同的Component实例进行注入,最后生成的对象还是不同的实例,即作用域管理的生命周期是跟随Component的。但一般情况下,我们一个APP只需要一份Component实例,而一个App中,往往有着不同的作用域

在MainActivity中,也定义注入一个SingleTest对象,注意每调用一次DaggerApplicationComponent.create(),会创新一个新的DaggerApplicationComponent对象

跳转到ScopeActivity后,我查看下打印结果:
2021-12-04/com.aruba.daggerapplication I/aruba_log: MainActivity singleton hashcode: 20446654
2021-12-04/com.aruba.daggerapplication I/aruba_log: singleton1 hashcode: 127836367
2021-12-04/com.aruba.daggerapplication I/aruba_log: singleton2 hashcode: 127836367

MainActivity和ScopeActivity中都调用了Component的create方法,所以两份Component实例注入的对象是不同的实例

如果想要一个Component下使用不同的作用域,Component是不支持的,但Subcomponent可以使用, Subcomponent又可以被添加到Component中

同时在子组件中提供注入方法,这边我新建了一个SubActivity

在Moudle注解中,指定使用哪个子组件

MainActivity中注入打印,并跳转到SubActivity

SubActivity中创建子组件,并注入

日志结果:
2021-12-04/com.aruba.daggerapplication I/aruba_log: MainActivity singleton hashcode: 257322958
2021-12-04/com.aruba.daggerapplication I/aruba_log: SubActivity singleton hashcode: 257322958
2021-12-04/com.aruba.daggerapplication I/aruba_log: SubActivity subObject1 hashcode: 219854405
2021-12-04/com.aruba.daggerapplication I/aruba_log: SubActivity subObject2 hashcode: 219854405

前两条证实了同一个父Component实例,就算使用子组件注入,作用域也有作用,后面两条说明我们成功的注入了子组件生成的对象

最后,附上一张dagger的结构图:

以上是关于Android--Dagger2入门的主要内容,如果未能解决你的问题,请参考以下文章

Android--Dagger2入门

Dagger2入门详解

Android Dagger2.0 学习一下

Android Dagger2,Singleton交叉组件

AndroidDagger2从入门到再入门(进阶)

Dagger2从入门到放弃再到恍然大悟