学习Dagger2笔记:【1】依赖与注入

目录

0. 前言
1. 依赖与注入
2. @Inject
3. @Module & @Provides
4. @Component
5. @Qualifier
6. Provider & Lazy
7. @Scope
8. 注入到Set和Map容器
9. Bind系列注解
10. dagger中依赖关系与继承关系
11. dagger.android

依赖与注入

都说dagger2是一个依赖注入的框架,那么什么是依赖,什么又是注入呢?下面以显示一台电脑的信息来举例:

  • 每台电脑(Computer)有其操作系统(os)和定价(price)
  • 电脑内有处理器(CPU),处理器有着自己的序列号(ID)
  • 电脑内有内存(Memory),内存有着自己的容量(size)
  • 电脑执行(execute)时,会分别执行处理器和内存,它们在执行时都将自己信息以文本方式返回

综上,我们将对应的这几个类都先写好:

class CPU {
    private val id = Random.nextInt()

    fun execute(builder: StringBuilder) { // CPU执行时返回自身序列号信息
        builder.append("CPU Id: ").append(id).append("\n")
    }
}

class Memory(private val size: Int) {
    fun execute(builder: StringBuilder) { // Memory执行时返回自身容量信息
        builder.append("Memory Size: ").append(size).append("MB\n")
    }
}

class Computer(private val os: String, private val price: Int) {
    lateinit var cpu: CPU
    lateinit var memory: Memory

    fun execute(builder: StringBuilder) { // CPU执行时除了返回自身信息,还要将CPU和Memory的信息一并返回
        builder.append("Computer OS: ").append(os).append("\n")
        builder.append("Computer Price: ").append(price).append("\n")
        cpu.execute(builder)
        memory.execute(builder)
    }
}

我们的Activity里面有这么一个电脑,并要将其信息显示出来:

class CaseActivity : AppCompatActivity() {
    lateinit var computer: Computer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_case)

        computer = Computer("Windows", 6666)
        computer.cpu = CPU()
        computer.memory = Memory(8192)

        show()
    }

    private fun show() {
        val builder = StringBuilder()
        computer.execute(builder)
        text_view.text = builder.toString()
    }
}

这里执行是没问题的,但可以发现ComputerCPUMemory这些对象都是由Activity创建的,但Case01Activity其实真正需要的只是Computer,为了得到这个ComputerCase01Activity不仅要为Computer准备好参数,甚至还要帮其创建CPUMemory!也就是说Activity不仅仅依赖Computer,甚至连Computer依赖CPUMemory)也变成Activity依赖,这样的耦合程度是相当严重的

上面那段话应该让你明白了什么是依赖,那么注入又是什么意思呢?让我们修改一下上面的例子:

object CaseActivityInjector { // 新创建一个类,目前可以看做是一个工具类
    fun inject(target: CaseActivity) { // 在此方法内创建Computer并注入到目标对象中
        target.computer = Computer("Windows", 6666).apply {
            cpu = CPU()
            memory = Memory(8192)
        }
    }
}

// 修改Activity的onCreate方法如下:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_case)
    
    CaseActivityInjector.inject(this)

    show()
}

如果只是从代码表面来看,无非就是关键代码从三行变成了一行,但为此我们却新建了一个工具类,有些自欺欺人的感觉;但如果我们从更高层次的思想去看待这个改动:

  • Activity确实只依赖于Computer了,而不会依赖于CPUMemory,实现了解耦
  • 原先创建ComputerCPUMemory的任务交给了Injector,实现了控制反转
  • Computer是通过Injectorinject方法注入Activity中的,而不是由Activity自行创建的

看到这,你或需对依赖注入都有了自己的认知,那么想想这样做的好处是什么?假设我有几十上百个Activity都需要显示Computer的信息,那么一旦我Computer结构改变了(比如添加了硬盘信息),在改动前我只能一个一个Activity去添加、修改代码,而改动后,我仅需修改inject中的实现。由此看来这个Injector是依赖注入中的核心部分,而dagger就是用来帮助我们生成这种**注入器(或者叫控制反转容器)**的框架,当然dagger生成的代码肯定不会像上面一样简单

总结

我眼中的依赖注入则是通过第三方容器(注入器、控制反转容器)将目标对象的依赖(成员变量)通过赋值的方式注入到目标对象中,使得目标对象不用考虑其依赖从哪里来、怎样构建、依赖的依赖等问题,而可以直接使用此依赖,即仅关注代码中真正起作用的对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值