初识Dagger2

 要使用Dagger2,首先要了解的就是控制反转和依赖注入这两个概念。

一、控制反转

 在wiki词条中,控制反转如下定义:In software engineering, inversion of control (IoC) describes a design in which custom-written portions of a computer program receive the flow of control from a generic, reusable library. A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the reusable code that calls into the custom, or task-specific, code.

 其中主要的含义就是客户端代码(custom-writen)可以控制一般性的可复用库的控制流(flow of control),比如组件对象的创建的控制权。
 控制反转和传统编程的对比:

  • IoC模式:调用类只依赖于接口,而不依赖于具体的实现类,减少了耦合。控制权交给了容器,在运行时才由容器决定将具体的实现动态的“注入”到调用类的对象中。
  • 传统编程:决定使用哪个具体的实现类的控制权在调用类本身,在编译阶段就确定了。

 所以,所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。而依赖注入则是控制反转实现的一种方式。

二、依赖注入

 先说依赖,依赖就是你两个代码模块的耦合(a dependency is a coupling between two modules of your code),一般来说,当对象A中还有类型为B的成员变量时,我们就可以说A依赖于B,二者就相互耦合,至于是何种耦合,那就要依情况而定。

 如果要避免这种依赖,我们可以设计一个interface IB,让B实现IB,然A依赖于IB,这就是所谓的依赖倒置原则。

 但是对于对象的创建,我们是无法规避所谓的依赖的,当你在一个对象中创建了另外一个类型的对象(new),就会产生依赖。所以在设计模式中,会有一系列的创建型模式来减少这类的依赖。

 从我现在对工厂模式和依赖注入的理解,二者在减少依赖这个方面的贡献应该是相同的,但是依赖注入可以减少你自己手写的代码。而依赖于反射的依赖注入在效率上会有所下降。

  A dependency is an object) that can be used (a service)). An injection is the passing of a dependency to a dependent object (a client)) that would use it. The service is made part of the client’s state).[1]
Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
 依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来(比如new出来应用组件对象),交给IoC容器负责,这样可以让程序准从依赖导致原则。

三、Dagger2

 Dagger2 是google从Dagger1中fork的一个分支。从一开始,Dagger2所秉承的观念就是使用代码自动生成和手写代码(类似于javabean的写一些有固定前缀的函数或者类,接口)来实现依赖注入。所以,Dagger2就有以下几点比较特殊的地方

  • 完全未使用反射,图的验证,配置和预处理都是在编译阶段完成。
  • 由于是通过生成代码来实现依赖注入,所以更容易调试和回溯异常路径,可以提供完整的调用函数栈。
  • 更高的性能,根据google的数据,性能提高了13%。
  • 不太灵活和动态,因为没有使用反射。

四、Dagger2使用

 具体的说明文档请查阅http://google.github.io/dagger/,这个demo在我的github上[https://github.com/ztelur/DaggerProject]

 这里只展示android上一个demo,解释各个注释的含义和一些常见的问题

  1 @Inject
按照标注的元素的不同,这个注释的作用不同

  • 标注元素为构造函数,当程序需要这个类型的对象时,就会
    调用这个构造函数,从而生成相应的对象,如果构造函数有参数,Dagger2会在调用构造函数之前先去获得这些对象,所以你要保证它的参数也提供了可以被Dagger2调用的构造函数
    标注在构造函数上
  • 标注元素为成员变量,这就标示,这个成员变量需要Dagger2来进行注入,也就是说Dagger2来初始化它,通常你需要调用Component.void injectSomeType(SomeType someType)这个方法来让Dagger进行自动化注入。
    标注在成员变量上
    inject函数

 2.@Module
module是拥有可以提供依赖的函数的类,我们定义一个类,标注为module,然后Dagger2就知道哪里可以找到构建一个对象所需要的依赖啦。而且module被设计为可以被分割和组合的模式,有益于模块的划分。

 3.@Provide:
在标注为module的类中的函数可以标注为provide,标示可以提供相应的依赖,函数的前缀必须为provides.
module和provide
 4.@Component
这是Dagger2依赖注入的核心模块,类似于一个注入器的角色。它是@Inject和@Module的桥梁。我们必须创建一个interface,标注为Component,然后列出所有它需要的Module。component中还可以提供一些方法来获得一些对象。component可以有scope,比如Application的生命周期,activity的生命周期,这一块我还没有搞清楚…..

 5.@Singleton
这是标示一个单例的注释,可以和provide共同标注一个函数,标示这个函数返回的对象都是单例的,也可以和component一起标注一个component,标示这个component的scope是全局的。
component
 6.Lazy injections
这个不是一个标注,而是一个可以推迟初始化的容器,比如你依赖一个对象B(@Inject B mB),但是你希望当你第一次使用它的时候在初始化,所以你就可以用Lazy(@Inject Lazy<B> mB)

五、Dagger2常见问题

  1. 如何在gradle上配置Dagger2:可以参考http://stackoverflow.com/questions/22976251/how-to-configure-dagger-gradle
  2. 程序包javax.annotation包不存在,找不到Generated:需要在Gradle中添加provided 'javax.annotation:jsr250-api:1.0'依赖

  3. 对于private的成员变量的注入问题:Dagger2是不支持private的成员变量的直接注入的。解决方法有两个:一个是换成protected,或者使用构造函数inject.但是这两种方法都没有良好的解决android平台中Activity,Application等类的注入问题.
    http://stackoverflow.com/questions/16598123/android-dagger-dependency-injection-fails-on-private-fields

  4. 对于第三方对象的注入问题
    https://github.com/google/dagger/issues/128#issuecomment-86702574
  5. 自定义scope问题:这个问题我一直没有搞懂,希望了解的同学帮助一下.
    http://stackoverflow.com/questions/29923376/dagger2-custom-scopes-how-do-custom-scopes-activityscope-actually-work
    http://stackoverflow.com/questions/28411352/what-determines-the-lifecycle-of-a-component-object-graph-in-dagger-2
    http://stackoverflow.com/questions/29923376/dagger2-custom-scopes-how-do-custom-scopes-activityscope-actually-work

六、后续

 这篇只是介绍关于Dagger2的背景知识和基本使用,之后我想研究一下Dagger2的源代码,和使用Dagger2对apk大小的影响。希望可以把这个系列做好吧。

#####Reference:

1000 Share