Dagger2 使用总结(一)
重阳节,又称重九节、晒秋节、“踏秋”,中国传统节日。庆祝重阳节一般会包括出游赏秋、登高远眺、观赏菊花、遍插茱萸、吃重阳糕、饮菊花酒等活动。
Dagger2是一套依赖注入框架,在编译期间自动生成代码,创建依赖的对象。项目中使用Dagger2可以降低代码的耦合度。 使用Dagger2库,重点是了解其中的各种注解并熟练使用,下面看一下具体用例。
注:为了能够更直观地了解Dagger2的使用,本文用例会尽量简化不相关的业务逻辑
环境配置
配置下build.gradle即可
@Inject和@Component注解
使用@Inject和@Component注解是Dagger2最基本的使用方式,来看一个简单的Demo,向 MainActivity 里注入 Apple:
编写 Apple类代码
编写 MainActivity 类代码
编译项目
这时候编译项目会在build目录下生成以下文件:
Apple_Factory.java DaggerMainActivity_MainActivityComponent.javaMainActivity_MembersInjector.java
这些文件是Dagger2框架帮我们自动生成的,用于帮我们注入依赖。
在 MainActivity 注入依赖
使用依赖注入
如果不使用依赖注入,那写法将会是下面这样:
这样看起来比不使用Dagger2注入对象要简单很多,但是如果对象引用的地方很多,构造复杂,那么一旦改变构造,工作量会很大,这也是Dagge2最重要的优势——解耦。
小结
以上是Dagger2最简单的使用方法,注入依赖后,会用在Apple类中标注@Inject注解的构造器自动创建apple对象。而@Component标注的接口用于连接目标类和注入类的工厂Apple_Factory。
方法注入
如果注入的对象需要设置为private,那我们可以使用方法注入,示例:
private Apple apple;@Injectpublic void setApple(Apple apple) { this.apple = apple; }
上述代码作用等同于:
@Injectpublic Apple apple;
拓展
如果现在需要修改Apple类的构造器,需要加一个Color参数,如下:
这时候构造器中的color也需要注入依赖,创建一个简单的Color类并在构造器上标注注解@Inject即可
这样在构建apple对象时会寻找标注了@Inject注解的Color的构造器新建color对象用于apple对象的构造。除了@Inject和@Component之外,Dagger2中还有其他注解,下文会说明。
@Modele和@Provides注解
@Inject注解存在局限性,以下两种情况时不能使用:
· 注入的对象来自第三方库
· 注入的对象声明为抽象类或接口(依赖倒置原则)
比如上述的例子修改下,添加一个抽象类Fruit:
修改后Apple类继承Fruit:
这时候,如果只按照下面的形式声明,是无法注入apple对象的,运行会报错
@Inject
public Fruit apple;
这时候就需要用到@Modele和@Provides注解,完整示例如下:
创建Fruit类和Apple类
Fruit抽象类:
Apple类:
创建Module类
在MainActivity中注入对象
小结
使用@Inject和@Component注解注入对象时, 我们需要在声明的注入类的构造器上加上@Inject注解来使对象被创建。
如果遇到注入类构造器不方便编辑时(比如来自三方库,抽象类,接口), 则可以使用@Module和@Provides注解,将对像获得由构造器获得转变为由方法返回,使对象的创建形式更加可控。
再形象看一下两者的区别(不想看可以跳过):
仅使用@Inject和@Component注入对象build目录下生成的文件如下 Apple_Factory.java DaggerMainActivity_MainActivityComponent.javaMainActivity_MembersInjector.java
使用@Module和@Provides注入对象build目录下生成的文件如下 FruitModule_ProvideAppleFactory DaggerMainActivity_MainActivityComponent.javaMainActivity_MembersInjector.java
区别在于前者是Apple_Factory.java而后者是FruitModule_ProvideAppleFactory, 这两个类都是用于提供对象的, 而DaggerMainActivity_MainActivityComponent.java类实现了MainActivityComponent接口, 用于将目标类和提供对象的类连接起来。
所以两者的区别仅在于提供对象的方式不同,再具体可以看这两个差异类的实现。
拓展
Component接口可以指定多个Module类,便于将它们一起注入,比如在这个例子中,可以按下述方式编写:
这样我们便可以注入OtherModule中可以获得的对象。
@Named注解
上述的@Module和@Provides注解仅能返回一个继承了Fruit的对象, 如果再加入一个Banana类,继承Fruit并在MainActivity中注入, 这时候就需要使用@Named注解。基于上述代码,示例如下:
新建Banana类
修改FruitModule类
修改MainActivity类
小结
@Named注解使用比较简单,只要将Module类中的标注和目标类中声明注入类的标注一一对应即可。
@Qualifier注解
@Qualifier注解的作用和@Named相同,只是实现有所区别,直接看示例:
修改FruitModule类
修改MainActivity类
小结
@Qualifier和@Named注解作用是一样的, 区别是@Named使用字符串来区分不同的返回对象,
而@Qualifier用自定义的接口来区分,这样可以提高代码的可读性,且不容易出错。
本文分享自 FreeSWITCH中文社区 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!