前言

  • 注解如同标签
  • 反射:GreenDao、Butterknife、Dagger2 这些因为涉及到了反射处理,而反射处理相对于正常开发速度很慢,所以它们通常在编译时产生一些新的代码,然后才能在程序运行过程中使用,也就是说它们都把反射处理移动到编译器编译代码时的阶段,而程序运行时并不涉及到反射,这就是这些框架运用了反射技术,但是仍然高效的秘诀所在。
  • 要先编译一次代码,不然就会报错。现在,可以解释了,编译代码是为了生成中间代码,然后在中间代码的基础上按照正常的流程开发。

依赖注入

class A {B b;C c;public A() {b = new B();c = new C(3);}
}
//————————————————
class A {B b;C c;public A(B b, C c) {this.b = b;this.c = c;}
}
/**
* 在上面代码中,A 不再直接创建 B 与 C,它把依赖的实例的权力移交到了外部,所以无论 B 和 C 怎么变* * 化,都不再影响 A 了。
* 这种实例化依赖的权力移交模式被称为控制反转(IoC)
* 而这种通过将依赖从构造方法中传入的手段就是依赖注入(DI)
*/

依赖注入的3种形式

构造方法注入

class A {B b;public A(B b) {this.b = b;}
} 

Setter 注入

class A {B b;public void setB(B b) {this.b = b;}
}

接口注入

interface Setter {void setB(B b);
}class A implements Setter{B b;public void setB(B b) {this.b = b;}
}

Dagger2

依赖注入框架
通过注解标记,Dagger帮我们完成实例化和注入。
Dagger2本质就是, 一个依赖注入框架,用来解耦。

@Inject

标记

  • 给属性做标记时:依赖的需求方(需求者)
  • 给构造方法做标记时:依赖的提供方(依赖)
public class Man {@InjectFoodRice foodRice;@Injectpublic Man() {}
}public class FoodRice {@Injectpublic FoodRice(){}
}

@Component

联系纽带,将 @inject 标记的需求方和依赖绑定起来,并建立了联系,
Dagger2 在编译代码时会依靠这种关系来进行对应的依赖注入

@Component()
public interface ManComponent {Man getMan();
}//build:makeBuild --> project模式 --> app --> build --> generated --> source --> apt --> debug//DaggerManComponent.builder().build().getMan().toString();

@Provides 和 @Module

  • Inject只能标记在我们自己写的类中,如果要提供第三方作为依赖对象就需要@Provides和@Module了
  • @Provides 注解的依赖必须存在一个用 @Module 注解的类中
  • 除了第三方无法Inject标记的在Module中提供,一些需要生成对象以后做其它初始化操作的也适合写到Module中
//没有提供Inject标记,视为无法改变的第三方类
public class LibClass {@Overridepublic String toString() {return "第三方类,不可修改\n";}
}@Module
public class ManModule {@Providespublic LibClass provideLibClass(){return new LibClass();}
}//在Component中关联该Module
@Component(modules = ManModule.class)
public interface ManComponent {
}public class Man {@InjectLibClass libClass;
}

无法控制生成实例的类进行依赖

  • 系统生成实例的类进行依赖,如Activity
/*
* 无法控制生成实例
*/
@Component(modules = ManModule.class)
public interface ManComponent {void inject(DaggerMainActivity activity);
}public class DaggerMainActivity extends BaseActivity {@InjectMan man;protected void initData() {DaggerManComponent.builder().build().inject(this);man.toString();}
}

实例需要特殊处理

public class FoodRiceEgg extends FoodRice {private String mType = "";public FoodRiceEgg() {}public void setType(String type){this.mType = type;}@Overridepublic String toString() {return "食物:"+mType+"蛋炒饭;\n";}
}@Module
public class ManModule {@Providespublic FoodRiceEgg provideFoodRiceRegg(){FoodRiceEgg riceEgg = new FoodRiceEgg();riceEgg.setType("金色的");return riceEgg;}
}public class Man {@InjectFoodRiceEgg foodRiceEgg;
}// 1. FoodRiceEgg extends FoodRice, 构造函数未改变,继承父类注解,所以这里不需要@Inject
// 2. Man中foodRiceEgg可以通Inject注解生成,也可通过Module获得,Module优先级高

提供依赖和注入的方式

提供依赖

  • Inject标识构造方法
  • 在Module中@Provide提供
    (Inject标识和Module中提供相同的依赖,以Module中优先)

@Component注入依赖(纽带)

注入的方式有两种:

  • 有Inject标识的返回该类型
  • 无法控制生成实例的,作为参数传入,进行依赖(如Activity)
@Component()
public interface ComponentTest {Man getMan();void inject(Activity act);
}

@Singleton 引出 @Scope

@Singleton
public class SingleBean {@Injectpublic SingleBean() {}
}//另外也可在Module中以Provide的方式提供
@Module
public class SecondActivityModule {@Provides@Singletonpublic TestSingleton provideTestSingleton(){return new TestSingleton();}
}@Singleton
@Component(modules = ManModule.class)
public interface ManComponent {Man getMan();void inject(DaggerMainActivity activity);
}// Man和Activity中Inject标注的实例就是单例的

@Scope

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}//@Singleton 所拥有的单例能力是以 Component 为范围的限定的
//@Singleton 起作用是因为它被 @Scope 注解。所以,我们也可以自己定义 Scope
//例如:以@PageScope来限定某一个依赖的作用域@Scope
@Documented
@Retention(RUNTIME)
public @interface PageScope {}

@Named和@Qualifiers

同类型、不同实例:

在Module中Dagger是根据返回类型确定要提供的依赖
如果是同类型不同实例,那就会混乱了

public class Man {@Inject@Named("name")String name;@Inject@StrPhoneString phone;
}@Module
public class ManModule {//1.@Named标注@Provides@Named("name")public String provideName(){return "Varmin";}//2. 自定义注解@Provides@StrPhonepublic String providePhone(){return "13439251326\n";}
}

@Qualifier

//@Name 只是被 @Qualifier 注解的一个注解。所以,它能够有效完全是因为 @Qualifier
//所以,我们也可以@Qualifier为元注解自定义注解,来区分同类型不同实例提供依赖时的区分@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {String value() default "";
}@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface StrPhone {
}

Component依赖

依赖:所以需要暴露接口
A依赖B,A想使用B的属性,就需要注入B的实例,并且B提供接口暴露出来

@Module
public class JobModule {@Providespublic Coder provideCoder(){return new Coder();}
}@Component(modules = JobModule.class)
public interface JobComponent {//自用无需写,被依赖需显示提供Coder getCoder();
}//这里如果只是想复用Coder,也可以直接使用多个Module,不必使用依赖的概念
//@Component(modules = {ManModule.class, JobModule.class})
@Component(modules = ManModule.class, dependencies = JobComponent.class)
public interface ManComponent {Man getMan();
}public class Man {@InjectCoder coder;
}DaggerManComponent.builder().jobComponent(jobComponent).build().getMan();/**
* 如果只是在DaggerJobComponent中使用Coder,因为有JobModule,所以那直接用就好了,不用在Component中显示提供接口。
* 但是在DaggerManComponent中,Coder是来自于依赖的JobComponent所有
* DaggerManComponent中需注入JobComponent实例,并通过实例中的接口获得Coder
*/

Component继承

继承:子类可以获取到父类能提供的所有类型
子类:用@Subcomponent标记
父类:返回SubComponent getSubComponent()类型

@Component(modules = ManModule.class)
public interface ManComponent {SubComponent getSubComponent();
}@Subcomponent()
public interface SubComponent {Man getMan();void inject(DaggerMainActivity activity);
}//Activity
@Inject
FoodRice foodRice;
...
@Inject
@Named("name")
String name;
DaggerManComponent.builder().getSubComponent().inject(this);// 在Activity中getSubComponent可以获取到ManComponent可提供的所有类型

Component生命周期

onCreate()中inject()方法调用完成后,Component实例就会因为没有被引用而被垃圾回收器回收.
需要注意的是,使用Lazy和Provider时,与该依赖对象有关的Module实例会被Lazy和Provider引用,所以该Module实例不会被垃圾回收器回收

懒加载、强制刷新

@Inject
Lazy<LazyBean> lazyBean;
@Inject
Provider<RefreshBean> refreshBean;lazyBean.get()
refreshBean.get()
refreshBean.get()

Dagger2的使用相关推荐

  1. java dagger2_java – Dagger2不生成Daggercomponent类

    Dagger2在Android工作室中没有生成任何组件类我知道它是一个已知问题,而我已经完成了几乎所有方法在我的android工作室中实现并尝试了各种教程但是每次我被击中这里,它都无法构建dagger ...

  2. Android -- 带你从源码角度领悟Dagger2入门到放弃(三)

    1, 前面两篇文章我们知道了怎么使用常用的四种标签,现在我们结合我们自己的项目中去简单的使用 在我们搭建项目的时候,一般会创建自己的Application,在里面进行一些初始化如一些第三方的Green ...

  3. Android依赖注入的实践——Dagger2

    个人博客CoorChice,https://chenbingx.github.io/ ,最新文章将会首发CoorChice的博客,欢迎探索哦 ! 同时,搜索微信公众号CoorChice,或扫描文章末尾 ...

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

    前言 dagger2的大名我想大家都已经很熟了,它是解决Android或java中依赖注入的一个类库(DI类库).当我看到一些开源的项目在使用dagger2时,我也有种匆匆欲动的感觉,因此就立马想一探 ...

  5. Dagger2从入门到熟练

    Dagger2是什么? 是一个依赖注入框架,butterknife也是一个依赖注入框架.不过butterknife,最多叫奶油刀,Dagger2被叫做利器啊,他的主要作用,就是对象的管理,无需显示调用 ...

  6. 深入浅出依赖注入框架Dagger2

    目录 目录 依赖注入 依赖注入实现的三种方式 1. 构造注入 2. 属性注入 3. 接口注入 Dagger2 Dagger2的引入 不带Module的Inject方式(Inject+Component ...

  7. 开发日记-20190512 关键词 Dagger2原理

    我记得我之前在日记里说过要写一篇关于dagger的文章,今天,恰好,网络炸了,有点时间来玩玩这些有意思的事情,表示,终于有机会将这些以前没有填上的大坑填上,自己的内心真的好开心,毕竟拖延症是很多人的习 ...

  8. Dagger2 知识梳理(1) Dagger2 依赖注入的两种方式

    一.资料推荐 最近这几天一直在看有关Dagger2有关的文章,感觉就是这东西真难用.真难懂,数次想要放弃,还好有网上大神的教程帮助,模模糊糊总算能把基本的几个概念跑通了. 这里首先推荐 牛晓伟 的下面 ...

  9. NSkyKit 项目实践-Dagger2

    kotlin中配置Dagger2 在app模块的build.gradle文件中进行如下配置, //daggerapi "com.google.dagger:dagger:$dagger_ve ...

最新文章

  1. python不同版本共存_多个python版本共存时的pip配置
  2. 说说自动学习,是什么样的境界和体验
  3. jenkins 安装maven 插件
  4. 刷卡芯片CI520可直接PIN对PIN替换CV520支持SPI通讯接口
  5. python回归分析结果怎么看_Python数据分析|线性回归
  6. 将字符串中的数字字符转换为对应的数字,并且求和输出
  7. gnuplot小功能
  8. web前端第一天练习
  9. Qt Central Widget
  10. 项目实训2021.07.08
  11. 2017计算机考证结果
  12. python爬取微博用户信息(六)—— 完整代码
  13. 网络视频直播平台怎么开发、有什么难点
  14. 统计学专业未来从事大数据方向有优势吗?
  15. 六层电梯西门子S7-200PLC梯形图程序
  16. 仅仅是一张照片就是不能刷脸支付的
  17. 求斐波那契数列前40项
  18. linux curl h 命令,Linux curl命令http cookie详解
  19. TC264代码移植遇到的问题
  20. 求职软件测试工程师英文简历,软件测试员英文简历范文【精选】

热门文章

  1. matlab电路环流,基于MATLAB的单芯电缆金属护套环流分析研究
  2. 记录一下vlfeat视觉库配置
  3. rabbitmq实战:高效部署分布式消息队列_一文看懂消息队列中间件--AMQ及部署介绍...
  4. Office 365和SFB更新
  5. IntelliJ IDEA Community 社区版配置 Web 开发环境(Gradle + Tomcat)
  6. [转] SQL Server中变量的声明和使用方法
  7. Linux 之alias 命令别名
  8. A*算法 javascript模拟
  9. Ruby如何使用require从外部加载自定义类或模块
  10. 使用 CommandBuilder 生成命令 (ADO.NET)