美文网首页述术
Kotlin、Dagger和Qualifier

Kotlin、Dagger和Qualifier

作者: 面包石头 | 来源:发表于2018-03-07 16:18 被阅读10次

1.背景


网上已经有很多大牛介绍过Dagger的原理以及使用方法了,说实在的,我在没有阅读代码的情况下,看大牛们的分析有一种尿急的感觉。于是我就去阅读代码了,天啊,我读不进去。别人写了教程读不懂,源码也读不懂,那怎么办呢。有点儿怀疑人生了,怎么别人懂得那么透彻,我就是不懂啊啊啊!

我写这篇文章的目的是不读源码,不分析原理,用的时候知道在哪里添加对应的方法。建议在读这篇前,先按照网上其他人的博客例子敲下。

2.gradle

  • 在gradle里添加dagger
    compile 'com.google.dagger:dagger:2.10'
    kapt 'com.google.dagger:dagger-compiler:2.10'
  • 在gradle的dependencies上面添加apt,这个可能是由于dagger会生成很多中间类所以要用apt,这个不用多管,知道怎么用就行了
kapt {
    generateStubs = true
}

3.四个注解


  • @Inject注解
  • @Module注解
  • @Component注解
  • @Provides

这么一看好牛叉啊,用四个注解就能完成依赖注入功能,你们是不是有什么特异功能?下面就说说这些注解到底是什么吧!

  • @Inject
    1. 你想让谁自动注入就在这个变量前加上这个注解,这里的变量指的是类的变量,方法里面的那种局部变量就不要想了。
  • 2.找到你加注解的这个变量对应的类,然后在构造方法里也加上这个注解。
  • 3.例子: class MainActivity{
    @Inject
    lateinit var mPresenter:MyPresenter
    }
    class MyPresenter @Inject constructor(var name:String){
    }
  • @Module和@Provides
  • 新建一个类,给这个类加上@Module注解。这个里面加什么方法呢?加第二个Inject注解构造方法里的参数,这个方法返回值是假Inject注解的构造方法里的参数类型,例如上面的var name:String,就加个方法返回值是String类型,然后给方法加个@Provides注解。
  • 例子: @Module
    class ActivityModule{
    @Provides
    fun provideString():String = "test_dagger"
    }
  • @Component
  • 新建一个接口类,用@Component标注
  • 添加个方法,名字随便取,参数是Inject注解里讲的MainActivity
  • @Component(modules = arrayOf(ActivityModule::class))
    interface ActivityComponent{
    inject(mA:MainActivity)
    }

4.导入

前面倒腾了这么多,运行起来还是不行,别着急,这一步会把上面生成的一些中间类(是这么叫吗?就是生成在app\build\generated\source\kapt\debug\包名 下面的那些)导入

DaggerActivityComponent.builder()
                .activityModule(ActivityModule())
                .build()
                .inject(this)

5.中间类

    1. ActivityModule_ProvideStringFactory
      这个类是根据ActivityModule类生成的,有@Provide标注的方法都会生成一个这样的类。如:在ActivityModule中添加如下代码会自动生成ActivityModule_ProvideIntFactory。这些ActivityModule开头的Factory类持有ActivityModule的引用,在get()方法中调用对应的方法。如,ActivityModule_ProvideStringFactory的get()方法返回的是activityModule.provideString();而ActivityModule_ProvideIntFactory的get()方法返回的是activityModule.provideInt()。
@Provides
fun provideInt():Int = 18
  • 2.MyPresenter_Factory
    这个类就是MainActivity中想自动导入依赖的类生成的中间类。还得看下MyPresenter带Inject注解的构造方法是什么类型,这里是String类型。那这个MyPresenter_Factory就持有ActivityModule_ProvideStringFactory类,get()方法返回的是new MyPresenter(ActivityModule_ProvideStringFactory.get())。这里是不是有点儿晕啊?MyPresenter的构造方法需要String类型------>ActivityModule_ProvideStringFactory类,因为只有这个类才能给它String,别人不给。咦,喂喂喂,等等,如果ActivityModule里面有两个返回值是String类型的方法,那不是就生成两个provideStringFactory类了吗?那要谁的值?别担心这样会编译报错。啊,原来这样。
  • 3.MainActivity_MembersInjector
    这个类的作用是MainActivity想自动导入几个变量,这个类就持有哪几个变量对应的Factory对象,如MyPresenter_Factory。然后,调用DaggerActivityComponent的inject方法时,由于传递了MainActivity对象,inject方法就是给mPresenter赋值为MyPresenter_Factory对象的get()方法返回值。所以,你想要自动注入的变量,不能声明为private。要不,它怎么赋值啊。

6.冲突

上面说了ActivityModule不能有两个加@Provides注解返回值类型一样。有时候就是有这种需求咋整?这就用到了@Qualifier注解。表达能力太弱了,直接上代码。

定义MyString注解
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class MyString
定义HisString注解
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class HisString
MyPresenter类
class MyPresenter @Inject constructor(@MyString val name:String) {
}
class HisPresenter @Inject constructor(@HisString val name:String) {
}
ActivityModule类
    @Provides
    @MyString
    fun provideString():String =
            "ActivityModule"

    @Provides
    @HisString
    fun provideHisString():String =
            "HisModule"

相关文章

网友评论

    本文标题:Kotlin、Dagger和Qualifier

    本文链接:https://www.haomeiwen.com/subject/ezpjfftx.html