Dagger2使用(1)

前言

Dagger2是现在非常火一个注入框架,网上一搜一大堆,看了之后一脸懵逼,还是不怎么懂,研究了一段时间之后,想自己去整理一下

Dagger2作用

  • 依赖的注入和配置独立于组件之外。
  • 因为对象是在一个独立、不耦合的地方初始化,所以当注入抽象方法的时候,我们只需要修改对象的实现方法,而不用大改代码库。
  • 依赖可以注入到一个组件中:我们可以注入这些依赖的模拟实现,这样使得测试更加简单。

依赖注入

what?依赖注入是什么东东?现在假设这是你的盲点,通过第一反应去解释一些"依赖注入"。依赖:需要你,need you。注入:给你。连接起来的意思就是:给你需要的,give you what you need。比如,你要去上班,怎么去呢?开车去,那么可以说你依赖于车;但是你现在没有车,于是你老爸给你买了一辆保时捷(有这样的老爸还上班做啥?),给你上班所需要的车,这就是注入。连接起来就是典型的依赖注入。不懂?那我们通过代码的来撸一撸。

 //定义一辆车
public class Car {
}  
//定义一个人,这个人需要一辆车。
public class Person {
Car car;

public Person(Car car) {
  this.car = car;
  }
}

上面这种是在构造Person的时候就注入了Car,因为Person需要一辆Car,而构造器正好可以注入Car。因此这是依赖注入的一种方式,我们还可以通过set方法去注入一辆Car

若是使用Dagger的方式又是怎样的呢,它能给我们带来什么好处?

public class Person {
// dagger2直接使用@Inject
@Inject
Car car;
}

你没看错,就是直接用@Inject注解就行了,非常的简单

实际操作

上文中通过"开车上班"的例子了解了什么是"依赖注入",那么我们继续这例子。我们知道车由发动机,轮子,车座等部件组成。那么,如果我们要造一辆车的话,可能需要这些部件。回归到代码中,我们new一个Car可能需要发动机,轮子,车座等对象。

我们先来看看没有使用Dagger2的情况

  • 发动机

    /**
     * 发动机
     */
    public class Engine {
    
    public Engine(){
    Log.d(Config.TAG,"new Engine()");
    }
    }
    
  • 车座

    /**
     * 车座
     */
    public class Seat {
    public Seat(){
      Log.d(Config.TAG,"new Seat()");
    }
    }
    
  • 轮子

    /**
     * 轮子
     */
     public class Wheel {
     public Wheel(){
      Log.d(Config.TAG,"new Wheel()");
      }
    }
    
  • 上面3个类用到了Config配置类,其实就是一个字符串。

    public class Config {
    public static final String TAG = "TAG";
    }
    

另话:把公共的部分抽取出来,也是代码规范的一部分。在今后的工作中,需要不断review自身代码,随着技术水平的提高,代码质量也需要不断提高。

上面的代码中,我们写了3个类,都是用来造车的构件。那么对于造车,对应于我们的代码就是new Car(),就是这么简单。但是Car可能需要Engine,Seat,Wheel 等组件。那么我们来造个车试试。

public class Car {
private Engine engine;
private Seat seat;
private Wheel wheel;
public Car() {
    engine = new Engine();
    seat = new Seat();
    wheel = new Wheel();
    Log.d(Config.TAG, "new Car()");
}
}

按照常规写法,Car类应该是这样写。那么我们在new Car()试试。

06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Engine()
06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Seat()
06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Wheel()
06-27 12:44:53.726 18967-18967/com.bae.basicandext D/TAG: new Car()

就这样,我们把Car给new出来了,这样写也是没有问题的。
那么接下来我们用Dagger2的方式,来做做试试,先不管他们之间的区别,just do it。做出来效果之后再回过头来反思。

Dagger2依赖注入

  1. 在module的build.gradle文件中添加

    annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2' 
    implementation'com.google.dagger:dagger:2.0.2'  
    provided 'org.glassfish:javax.annotation:10.0-b28'
    
  2. 写一个Module类,管理上面的三个依赖。

     @Module
     public class CarModule {
     @Provides
     public Engine provideEngine(){
         return new Engine();
     }
    
     @Provides
     public Seat provideSeat(){
         return new Seat();
     }
    
    @Provides
     public Wheel provideWheel(){
     return new Wheel();
     }
     }
    

3 写一个Component类,来连接Module和你的Car。

@Component(modules = CarModule.class)
public interface CarComponent {
void inject(Car car);
}

4 重写Car类

public class Car {

@Inject
Engine engine;
@Inject
Seat seat;
@Inject
Wheel wheel;
public Car() {
  DaggerCarComponent
        .builder()
        .carModule(new CarModule())
        .build()
        .inject(this);
Log.d(Config.TAG, "new Car()");

}
}

看看输出

06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Engine()
06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Seat()
06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Wheel()
06-27 13:03:25.447 26227-26227/com.bae.basicandext D/TAG: new Car()

是不是达到了和之前一样的效果呢?是不是从第3步开始,就不知道为什么这样写了呢?

分析

我们看看CarModule类是用一个@Module注解的类,里面的方法是使用@Provides注解。什么意思呢?
@Moudle 表示该类能够管理并提供依赖;你需要造车,但是车依赖于发动机,轮胎以及车座,那么写一个@Module注解的类来帮你管理这些依赖。
@Provides 表示该方法提供依赖;通过这个注解的方法,能给你提供依赖,看代码应该清楚。

我们知道了管理并提供依赖的类,那么我们就可以通过它来直接使用依赖。但是Dagger2为了解耦,提供了一个中介,@Component注解,也就是我们的第4步。

@Component(modules = CarModule.class)
public interface CarComponent {
 void inject(Car car);
}

我们要清楚,@Component就是一个中间人,里面存着依赖提供者和依赖需求者。在这里

@Component(modules = CarModule.class)

表示的是需要在CarModule类中去寻找依赖,void inject(Car car);这个方法是抽象的,表示需要将这些依赖应用到Car类。说白了就是Car类需要CarModule来提供依赖。

那么我们来看看@Component的官方文档。

* Annotates an interface or abstract class for which a fully-formed,     dependency-injected
* implementation is to be generated from a set of {@linkplain #modules}.

说的是这个注解只能用于接口或者抽象类。将代码改成下面,输出也是一样的。

@Component(modules = CarModule.class)
public abstract class CarComponent {
public abstract void inject(Car car);
}

在上面的步骤中,我们搞定了依赖提供者,中间人,现在我们要看看依赖需求者。在这我们的需求者是Car,也就是上面写的Car类。

我们用到了@Inject注解,

@Inject
Engine engine;

上面的代码表示engine这个属性你不用像一般情况去初始化(engine= new Engine()),它能给你自动寻找依赖。但是如果是这样肯定是不行的,还需要

 DaggerCarComponent
    .builder()
    .carModule(new CarModule())
    .build()
    .inject(this);

DaggerCarComponent是apt工具帮我们生成的类,实现了CarComponent接口。
通过carModule()将我们的依赖提供者传入,通过inject()将我们的Car对象传入,这样就达到了中间人的目的。

推荐两篇写的比较好的文章,Dagger2 最清晰的使用教程
Dagger2神器入门

如果大家对我的文章感兴趣的话, 请为我点赞,谢谢!!!

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

推荐阅读更多精彩内容