Kotlin、Dagger和Qualifier

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"
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容