Android开发-Dagger2学习记录

前言

Dagger2是目前Android流行的框架搭配之一。所以,学起来!(P.s:看了好多好多的文章解读~)

原理解读

Dagger2是什么?

官方介绍:

A fast dependency injector for Java and Android.

译:Java和Android的快速依赖关系注入器。

个人理解:Dagger就是用来创造出一个容器,所有需要被依赖的对象在Dagger的容器中实例化,并通过

Dagger注入到合适的地方,实现解耦。

什么是依赖注入?

依赖注入,英文名Dependency Injection,简称DI。简单说就是目标类(目标类需要进行依赖初始化的类)中所依赖的其他的类的初始化过程,不是通过手动编码的方式创建,而是通过技术手段可以把其他的类的已经初始化好的实例自动注入到目标类中。(P.s:不明白没关系,看文章你就明白了!认真脸!)

优点

  • 增加开发效率,神曲重复的简单体力劳动
  • 更好的管理类实例
  • 解耦
  • 便于扩展和维护

缺点

  • 相对于其他框架,有一定学习成本,需要时间消化。我自己就看了好多好多文章。。。。

少废话!入正题!

Dagger2提供的注解:@Inject@Component@Module@Provieds

在描述第一组注解的作用前,我们来看一则例子:

​ 假设领导下午要出去视察民情,需要一辆公交车,司机就不用请了,领导做表率自己开,小秘把领导的指示告诉了车场调度员。
  找辆公交车要停放在停车场(Bus要注入到ParkingActivity),停车场不管公交车按什么路线停车(ParkingActivity不管Bus是如何注入的),车场调度员会负责好管理(Dagger2容器会将Bus的注入到ParkingActivity)。

public class Bus {
@Inject
public Bus() {
}
}

public class ParkingActivity extends Activity {
@Inject
Bus mBus;
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_dagger);
  DaggerParkingComponent.create().inject(this);//DaggerParkingComponent类需要编译才会生成
  ((TextView) findViewById(R.id.text)).setText(mBus.toString());
}
}

@Component
public interface ParkingComponent {
void inject(ParkingActivity activity);
}

DaggerParkingComponent类是编译过后Dagger2自动生成的,是ParkingComponent的实现类,可以说DaggerParkingComponent就是实际的车场调度员,ParkingComponent是对车场调度员的约束,在onCreate方法完成了注入过程。

@Inject的作用

(1)注解在属性中表示该属性需要依赖注入,不能使用private修饰,示例代码表示需要注入属性

mBus(Bus的车位):

@Inject
Bus mBus;

(2)注解在方法中表示该方法需要依赖注入,不能是抽象方法,不能使用private修饰,示例代码表示

​ 需要注入方法injectBus:

//@Inject
Bus mBus;
@Inject
public void injectBus(Bus bus) {
mBus = bus;
}

​ 方法注入的参数同样由Dagger2容器提供,以上代码的目的与第一点介绍的属性注入一样,都是为

了注入mBus,如果目的是注入属性的话,方法注入和属性注入基本没有区别,属性注入是Dagger2中使用最多的一个注入方式。
  那么什么情况下应该使用方法注入?比如依赖需要this对象的时候,方法注入可以提供安全的this对象。
  注意,Dagger2容器先调用属性注入,然后再方法注入,若把示例代码mBus@Inject取消注释,此时mBus会注入2次,并且两次注入的Bus也不相同。

(3)注解在构造方法中表示此类能为Dagger2提供依赖关系,Dagger2可以使用这个构造方法构建对象(Bus的来历):

@Inject
public Bus() {
}

​ 如果有多个构造函数,只能注解一个,否则编译报错。

@Component的作用

一般用来注解接口,被注解的接口在编译时会生成相应的实例。实例名称一般以Dagger为前缀,作为所需注入依赖(ParkingActivity的mBus属性)和提供依赖(Bus类构造方法)之间的桥梁,把提供的依赖)注入到所需注入的依赖中(ParkingActivity的mBus属性)。

例子一总结:通俗说,就是Dagger2的容器,在例子中是车场调度员,把公交车和停车场联系在一起。车场调度员知道停车场要准备一辆公交车,停车场不需要知道车是哪里来的,也不需要知道怎么停,车场调度员找好车后,停在车位上就完事,等候领导用车就可以了。

两个@Inject注解形成了依赖关系,@Component作为连接这个关系的桥梁存在,寻找到依赖并且注入,并且注入与被注入之间互不干涉,经过编译@Component生成Dagger为前缀的实例,调用实例的方法。

第二组注解例子:

领导想着不妥,自己没开过公交车,为保险起见还是赶紧吩咐小秘,去给配个公交车司机,小秘自然跟车场调度员说了。
  车场调度员一想,只是比之前多了一个步骤,给公交车配置一个司机(Bus类添加String类型Driver构造方法)。于是打电话给开公交车的隔壁老王,老王自然是应诺了下来,于是乎,对例子一的代码做一下修改。

public class Bus {
   private String driver;
   @Inject
   public Bus(String driver) {
       this.driver = driver;
   }
}

public class ParkingActivity extends Activity {
   @Inject
   Bus mBus;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_dagger);
       DaggerParkingComponent.create().inject(this);//DaggerParkingComponent类需要编译才会生成
       ((TextView) findViewById(R.id.text)).setText(mBus.toString());//重写Bus的toString()方法能看到打印出"隔壁老王",注入成功
   }
}

@Component(modules = ParkingModule.class)
public interface ParkingComponent {
   void inject(ParkingActivity activity);
}

@Module
public class ParkingModule {
   public ParkingModule() {
   }
   @Provides
   public String provideDriver() {
       return "隔壁老王";
   }
}
@Module的作用

该注解与@Provides结合为Dagger2提供依赖关系,对上文@Inject第三点的补充,用于不能用@Inject提供依赖的地方,如第三方库提供的类,基本数据类型等不能修改源码的情况。

@Provieds的作用

@Provides仅能注解方法,且方法所在类要有@Module注解。注解后的方法表示Dagger2能用该方法实例对象提供依赖。按照惯例,@Provides方法的命名以provide为前缀,方便阅读管理。

例子二总结:首先@Component注解包含了一个ParkingModule类,表示Dagger2可以从ParkingModule类查找依赖,Dagger2会自动查找ParkingModule类有@Provides注释的方法实例依赖,最后完成注入。
注意1,如果在ParkingModule里面同样提供Bus的依赖,Dagger2会优先在@Module注解的类上查找依赖,没有的情况才会去查询类的@Inject构造方法,如下面的代码,则Bus的司机就是小王而不是老王了。

@Module
public class ParkingModule {
   public ParkingModule() {
   }
   @Provides
   public String provideDriver() {
       return "隔壁老王";
   }
   @Provides
   public Bus provideBus() {
       return new Bus("楼上小王");
   }
}

注意2@Module类可以从构造方法传入依赖,@Provides方法也可以有依赖关系。
@Provides方法也有依赖关系的情况,Dagger2会继续查找可以提供依赖的方法,类似于一种递归的状态,一步一步返回实例。如下代码,ParkingModule构造方法传入driverprovideDriver方法提供依赖返回,provideDriver返回driver作为provideBus方法的依赖实例Bus
ParkingModule加入有参构造方法后,调用方式也需要变成,现在司机就变成了楼下老李了。

@Module
public class ParkingModule {
   private String driver;
   public ParkingModule(String driver) {
       this.driver = driver;
   }
   @Provides
   public String provideDriver() {
       return driver;
   }
   @Provides
   public Bus provideBus(String driver) {
       return new Bus(driver);
   }
}
   //调用方式改变
   DaggerParkingComponent.builder().parkingModule(new ParkingModule("楼下老李")).build().inject(this);

总结

最后,来总结下依赖注入的大致流程:

1:查找Module中是否有该实例的@Provides方法。

  • 1.1:有,走第2点。

  • 1.2:没有,查找该实例是否有@Inject构造方法。

      1.2.1:有,走第3点。

      1.2.2:没有,注入失败。

2:@Provides方法是否有参数

  • 2.1:有,则回到第1点查找每个参数的依赖
  • 2.2:没有,实例该类返回一次依赖

3:@Inject构造方法是否有参数

  • 3.1:有,则回到第1点查找每个参数的依赖
  • 3.2:没有,实例该类返回一次依赖

4:以上流程递归返回注入目标的所有依赖,最后依赖注入。

参考链接

dagger2让你爱不释手-基础依赖注入框架篇

google四件套之Dagger2。从入门到爱不释手系列

Android Dagger2 从零单排系列

Dagger2使用

Dagger2简单入门

浅析Dagger2的使用

Android_Dagger2篇——从小白最易上手的角度 + 最新dagger.android

Dagger2 最清晰的使用教程

dagger2到底有哪些好处

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

推荐阅读更多精彩内容