一.dagger2是一个依赖于编译器实现自动依赖注入的库
那么它是怎么实现依赖注入的?依赖从哪里来?又要注入到哪里去?这篇文章先来讲讲依赖从哪里来
二.中介者Component组件
获取依赖和注入依赖都依赖于Component组件,Component组件类就像一个中介者,链接依赖类和注入类。 怎么定义一个Component?很简单,接口+@Component注解
@Component
interface ProvideComponent {}
dagger2是一个依赖于编译器实现自动依赖注入的,因此学习Dagger2一定要看看编译器生成的类是咋样的。
三.依赖从哪里来?
- 通过@Inject注解:在依赖类的构造函数添加@Inject,并在@Component注解的组件接口中定义获取依赖的方法,然后再编译一下看看自动生成组件类
class Pig @Inject constructor():Animal{ override fun description(){ println("我是小猪佩奇,通过@Inject提供") } }可以看到组件类可以通过@Inject注解的构造函数提供依赖类了
- 通过@Module注解:想要获取接口或第三方库中类的依赖时,没办法通过@Inject的方式,那么此时可以用@Module的方式提供;而且如果同时用两种方式提供依赖,那么中介者最终只会采用@Module注解方式
使用方式:
- 在提供依赖的类上添加 @Module 注解
- 在提供依赖的类的方法上添加 @Provides/@Binds 注解
- 在Comment 上@Component注解上添加相应的参数(如ProvideComponent的(modules = [ParamModule::class]))
@Module class ParamModule constructor(val name:String) { @Provides fun provideFish():Fish{ return Fish(name) } }@Component(modules = [ParamModule::class]) interface ProvideComponent { fun getPig(): Pig fun getFish():Fish }可以看到Fish最终是由ParamModule类提供的 fun main() { //静态方法create()快速创建Dagger组件 //DaggerProvideComponent.create().run { // getPig().description() // } //建造者模式创建Dagger组件,当组件需要传值时(如添加了有参构造函数的ParamModule时)一定得>使用建造者模式创建 //并且需要手动设置module,不然会报错 DaggerProvideComponent.builder().paramModule(ParamModule("鲤鱼泡泡")).build().run { getPig().description() getFish().description() } }
- 通过自定义中介者Builder和@BindsInstance注解。module类的构造函数参数最多只能有一个形参,而这种方式能代替module构造函数传参,且没有个数限制。这种方式和@Module注解方式不能同时提供依赖类(使用了限定符注解的情况除外),且优先级也是比@Inject注解方式高的
@Component interface BindsInstanceComponent { fun getName():String @Component.Builder interface Builder{ @BindsInstance fun userName(name:String):Builder //返回中介者的方法必须要定义 fun build():BindsInstanceComponent } }fun main(args: Array<String>) { DaggerBindsInstanceComponent.builder().userName("gyq").build().run{ println("name: ${getName()}") } }