今天接触了Dagger这套android的依赖注入框架(DI框架)。感觉跟Spring 的IOC差点儿相同吧。这个框架它的优点是它没有採用反射技术(Spring是用反射的),而是用预编译技术。因为基于反射的DI非常地耗用资源(空间,时间)

因为如今开发都是用Android Studio了,所以我这里大概讲下配置Dagger框架的开发环境。须要怎么做。

(因为Android Studio中用Gradle。所以跟传统我们用Eclipse配置的话。直接导入jar包,有点不一样。

在開始看我的博文前。希望大家有时间能够自己看下Dagger官网的文档:http://square.github.io/dagger/

相应的中文翻译:http://fanxu.me/post/2013-07-18#main(主要就是这篇文章翻译得非常具体,就是太长了,我主要对这文章进行了自己的理解还有自己的浅析哈,所以假设你时间充裕,而且足够耐心。能够先看这个。)

Dagger是构建在Android annotations的基础上的。假设你还不知道关于Android annotations,能够先看看我之前的一篇文章。

Android annotations浅析:http://blog.csdn.net/ljphhj/article/details/37601173


一、Android Studio 配置 Dagger 开源框架环境

1、建立一个module

2、在module中会有build.gradle的文件

3、在文件里的下列位置增加两行红色字体

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:19.+'
    compile 'com.squareup.dagger:dagger:1.2.+'
    provided 'com.squareup.dagger:dagger-compiler:1.2.+'

}

二、Dagger浅析

1、不论什么新生事物的产生都有其特定的历史背景,为什么会出现Dagger框架呢?

Dagger框架为了简化你的代码,让你把你的注意力转移到真正须要关注的类上,比方:

我们常说要通过工厂类来创建出产品类对象。

可是,往往我们更重视的是产品类,而并非工厂类,更不是它的生产过程。

2、Dagger框架怎么用?

Dagger框架图:

首先我要用大白话的形式让大家明白几个概念:

(以下类设计未必合理。仅仅为了让大家更好地理解)

1.@Inject注入对象

public class ClassRoom{

@Inject Student student1; //加上这个注解@Inject。 表示当前类ClassRoom要注入这样一个类Student的对象

//可是竟然我前面说Dagger不是通过反射机制。而是预编译的技术,那么它要怎么知道Student类对象由谁提供出来呢?

}

2.因为注入对象没有一个提供对象的地方是不能够的,所以引出了@Provides注解, 和 @Module的概念

//因为@Provides要包括在@Module凝视的类中,所以仅仅要函数中出现了@Provides就必须要在类上面加上@Module注解

@Module

public class StudentModule{

//加上了@Provides的方法,Dagger会去识别它的返回类型,当发现它的返回类型是Student类,上面第一步的@Inject就会来调用它,完毕注入。

@Provides Student provideStudent(){

return new Student();

}

}

约定@Provides函数以provide作为前缀, @Module类以Module作为后缀。

假设以上的你都理解了,那么接下来的东东就好办了!!

3.当我们希望无论多少个地方注入Student这个类。我们仅仅希望拥有一份“Student”的实例对象(单例),那么我们能够用到注解@Singleton 加在 @Provides注解的后面就可以

@Provides @Singleton Student provideStudent(){

return new Student();

}

@Singleton 凝视对Dagger有效, 也仅仅在一个ObjectGraph中生效。 若是有多个ObjectGraph。 则有多个相应的@Singleton对象。

4.延迟注入 Lazy :(即:懒载入, 等到调用的时候才注入)

public class ClassRoom{

@Inject  Lazy<Student> lazyStudent;

public void study(){

lazyStudent.get();//这样就能得到一个Student对象

}

}

5.提供者注入 Provider

有些情况下, 你须要多个对象实例。 而不是仅仅注入一个对象实例。这时你能够利用Provider实现, 每次调用Provider的get()函数将返回新的<T>的对象实例。

public class ClassRoom{

@Inject  Provider<Student> providerStudent;

public void study(){

providerStudent.get(); //得到对象1

providerStudent.get(); //得到对象2

//对象1 和 对象2 是两个不同的对象.

}

}

6.限定符注解 @Qualifier : 个人认为有点像 “Web中自己定义标签”的感觉,也有点像 "C语言里宏定义" 的样子。

有些时候,单纯类型(指这些主要的@Inject....等等)是不能够满足指定依赖的需求的。

在这种情况下,我们能够增加限定符凝视. 这种凝视本身有一个@Qualifier凝视。

以下是javax.inject中@Named的声明代码:

  1. @Qualifier
  2. @Retention(RUNTIME)
  3. public @interface Named {
  4. String value() default "";
  5. }

这样写完之后,我们就新拥有了一个注解@Named, 来帮助我们限定我们想提供的类对象,还有我们获得的类对象的实例。

如:

public class ClassRoom{

@Inject @Named("胖虎") Student pangHu;

@Inject @Named("李四") Student liSi;

//这样就限定了所要获取的Student类对象实例的性质了

}

那么我们之前说必须要有提供 类对象实例的方法,那么如今有限定符的话,我们要怎么来写这种方法呢?

@Module

public class StudentModule{

@Provides @Named("胖虎") Student providePangHuStudent(){

return new Student("胖虎");  //假设该Student类有个这种构造函数

}

@Provides @Named("李四") Student provideLiSiStudent(){

return new Student("李四");

}

}

依赖关系也能够同一时候有多重限定符凝视。

7.静态注入(staticInjections):建议慎重使用这个特性。 因为静态依赖注入非常难測试和复用。

Dagger能够注入静态变量。

拥有@Inject静态变量的类必须在@Module的staticInjections中明白说明。

  1. @Module(
  2. staticInjections = LegacyCoffeeUtils.class
  3. )
  4. class LegacyModule {
  5. }

能够使用ObjectGraph.injectStatics()注入静态变量:

  1. ObjectGraph objectGraph = ObjectGraph.create(new LegacyModule());
  2. objectGraph.injectStatics();

8.编译时有效性的检查(这个非常重要)

Dagger包括一个annotation 处理器, 这个处理器检查module和注入的有效性。处理器非常严格, 若是有不论什么绑定是无效或者不完整的, 将引发编译错误。

那么应该遵循什么样的规则呢?我举官网上的一个样例来跟大家分析下哈。

@Module
public class DripCoffeeModule {

@Provides

Heater provideHeater(Executor executor) {
    return new CpuHeater(executor);
   }

}

分析:因为我们知道。provideHeater是在有别的类@Inject了Heater类(或子类)的时候。会来调用这种方法。也就是说这个全然是由Dagger框架来调用的,而并非传统意义上我们自己调用这个函数。

那么问题应该就非常明显了吧???

这个參数。应该要由我们来提供吧?肯定有一个@Module里面有一个方法是叫做 provideExecutor(), 可是我们这边也不能用@Inject来注解这个參数。那要怎么让我们这个当前类。知道要去找那个方法拿这个參数呢?

有两种方法:

1.把这个provideExecutor()方法放入到我们这个类中来,这样子它就能够找到这种方法并进行注入这个參数对象了。

2.在@Module中增加一个參数 complete=false, 标记说明该Module为不完整的Module。

因为不完整的Module同意缺少对象实例

@Module(complete=false)
public class DripCoffeeModule {

@Provides

Heater provideHeater(Executor executor) {
     return new CpuHeater(executor);
   }

}

另一个比較难理解的就是关于injects了

是这种,假设在@Module中增加參数injects (即所谓的:注入对象列表绑定)。

若是这个Module提供的对象绑定。 可能被injects列表中以外的类使用, 能够将改Module标记为library, 以避免出错。

如:

@Module(

injects = ClassRoom.class,

library = true

)

public class StudentModule{

@Provides Student provideStudent(){

return new Student();

}

@Provides Others provideOthers(){

return new Others;

}

}

分析:因为ClassRoom中仅仅用到了一个Student的类,而injects列表中也仅仅写了ClassRoom.class, 这种话。这个类提供的其它方法有可能被除了ClassRoom之外的类所用,那么避免报错就要在@Module加上參数library=true

9.全部@Provides要放在一个@Module中

因为Dagger规定全部@Provides要放在一个@Module中。所以我们要么能够在一个Module中用includes參数把其它的Module类包括进来

或者比較建议的是:再创建一个空的Module类,把全部的Module都包括到这个Module中来。

  1. @Module(
  2. includes = {
  3. StudentModule.class,
  4. ExecutorModule.class
  5. }
  6. )
  7. public class AppModules {
  8. }

10.Module重载(引用官网的样例): 了解下就能够了

若对同一个依赖关系有多个@Provides函数, Dagger 将会报错。

但在有些情况下,是有必要替换production代码的, 比方測试和开发。 在@Module中能够使用overrides =true 。 重载其绑定关系。
以下这个JUnit測试利用Mockito, 重载了DripCoffeeModule的Heater绑定关系。这个Mock对象将inject到CoffeeMake中。

  1. public class CoffeeMakerTest {
  2. @Inject CoffeeMaker coffeeMaker;
  3. @Inject Heater heater;
  4.  
  5. @Before public void setUp() {
  6. ObjectGraph.create(new TestModule()).inject(this);
  7. }
  8.  
  9. @Module(
  10. includes = DripCoffeeModule.class,
  11. injects = CoffeeMakerTest.class,
  12. overrides = true
  13. )
  14. static class TestModule {
  15. @Provides @Singleton Heater provideHeater() {
  16. return Mockito.mock(Heater.class);
  17. }
  18. }
  19.  
  20. @Test public void testHeaterIsTurnedOnAndThenOff() {
  21. Mockito.when(heater.isHot()).thenReturn(true);
  22. coffeeMaker.brew();
  23. Mockito.verify(heater, Mockito.times(1)).on();
  24. Mockito.verify(heater, Mockito.times(1)).off();
  25. }
  26. }

这种重载方式也非常适合程序的小型变动, 比如付费版。免费版。

Android Dagger依赖注入框架浅析的更多相关文章

  1. [Android]依赖注入框架google的dagger

    分享一下Android依赖注入框架--Google升级版Dagger2框架 Google的Dagger2是对上一版squareup的Dagger改版,话不多说直接上项目代码. Dagger2源码 Da ...

  2. [Android]依赖注入框架squareup的dagger

    分享一下Android依赖注入框架--Dagger使用 Dagger源码 Dagger1-Demo 希望能给大家的开发带来帮助.

  3. 放弃dagger?Anrdoi依赖注入框架koin

    Koin 是什么 Koin 是为 Kotlin 开发者提供的一个实用型轻量级依赖注入框架,采用纯 Kotlin 语言编写而成,仅使用功能解析,无代理.无代码生成.无反射. 官网地址 优势 依赖注入好处 ...

  4. [Android]Android MVP&依赖注入&单元测试

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5422443.html Android MVP&依赖注入 ...

  5. 依赖注入框架之dagger2

    主页: https://github.com/google/dagger 历史 * Dagger1是由Square公司受到Guice(https://github.com/google/guice)启 ...

  6. 简单谈谈Hilt——依赖注入框架

    今天继续Jetpack专题,相信不少的朋友都使用过Dagger,也放弃过Dagger,因为实在太难用了.所以官方也是为了让我们更好使用依赖注入框架,为我们封装了一个新的框架--Hilt,今天一起来看看 ...

  7. 史上最好用的依赖注入框架Google Guice【转】

    Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IOC).Guice非常小而且快. (其他的依赖注入框架还有Dagger,Spring) Spring ...

  8. 依赖注入及AOP简述(四)——“好莱坞原则”和依赖注入框架简介 .

    3.2.    “好莱坞原则” 看了前面关于依赖注入概念的描述,我们来提炼出依赖注入的核心思想.如果说传统的组件间耦合方式,例如new.工厂模式等,是一种由开发者主动去构建依赖对象的话,那么依赖注入模 ...

  9. Ninject是一款.Net平台下的开源依赖注入框架

    Ninject是一款.Net平台下的开源依赖注入框架.按照官方说法,它快如闪电.超级轻量,且充分利用了.Net的最新语法,使用Lambda表达式代替Xml文件完成类型绑定.Ninject结构精巧,功能 ...

随机推荐

  1. 一些CSS常见的小问题小笔记

    父元素与子元素之间的margin-top问题: 给子元素盒子一个垂直外边距margin-top,父元素盒子也会往下走margin-top的值 解决方法: 1.修改父元素的高度,增加padding-to ...

  2. php byte数组与字符串转换类

    <?php /** * byte数组与字符串转化类 * @author ZT */ class Bytes { /** * 转换一个string字符串为byte数组 * @param $str ...

  3. 20145301&20145321&20145335实验一

    这次实验我的组员为:20145301赵嘉鑫.20145321曾子誉.20145335郝昊 实验内容详见:实验一报告

  4. HTML之DOM

    对于B/S开发,客户端与服务器端的交互是非常必要的,JavaScript的提出解决了很多问题,AJAX的提出也解决了异步通信的问题,更加为用户着想了.而DOM是其中非常基础的知识,在学习AJAX的同时 ...

  5. SQLSERVER DBA容易犯的十个错误

    SQLSERVER DBA容易犯的十个错误 翻译自:http://sqlsentry.tv/top-10-administrative-mistakes-on-sql-server/ 除了排名前十的错 ...

  6. SQLSERVER 里经常看到的CACHE STORES是神马东东?

    SQLSERVER 里经常看到的CACHE STORES是神马东东? 当我们在SSMS里执行下面的SQL语句清空SQLSERVER的缓存的时候,我们会在SQL ERRORLOG里看到一些信息 DBCC ...

  7. 在线教学、视频会议 Webus Fox(2) 服务端开发手册

    上次在<在线教学.视频会议软件 Webus Fox(1)文本.语音.视频聊天及电子白板基本用法>里介绍了软件的基本用法.本文主要介绍服务器端如何配置.开发. 1. 配置 1.1 IIS配置 ...

  8. T4 模板 : 一种提升ASP.NET MVC开发速度方法

    最近由于需要在框架中提供一些自定义模板的功能,找到了一篇博客,可惜似乎是翻译工具直接翻的,读不通顺,就试着自己翻译下,我不会完全翻译原文的句子,可能会对原文进行小范围的我认为更合适的句子并添加些注释, ...

  9. BugTracker 加入发Mail的功能

    BugTracker部署好之后,发现增加bug不能mail提醒.于是补上这个功能记录在此,方法是次要的,主要是找到地方.需要3步.吐槽下Asp的代码风格看的真心蛋疼.... 一.发送mail(主要是找 ...

  10. EDA系列学习

    发布这系列的EDA课程VHDL实验是因为有着和单片机系列同样的理由,另外,这个系列的文档只进行过波形图仿真,部分的程序可能不能在硬件上运行. 目录 实验二 8位加法器设计 实验三 组合逻辑电路的VHD ...