前言

   java注解除了解耦个人认为还有使代码简洁、逻辑更加突出业务逻辑代码、由于创建对象的集中,更加方便对象的维护与测试、对象的创建和生命周期的管控都交由框架等优点。

Dagger2的历史:

  Dagger1是Square公司开发,Dagger2则由谷歌接收在dagger1的分支上开发而来,Dagger1用了反射,消耗了一些性能,Dagger2则被谷歌声称性能提高了13%,但是其灵活性减少

Dagger2的使用

添加依赖:

implementation 'com.google.dagger:dagger:2.4'
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'

创建一个实体类:

public class DaggerTestBean {private String msg="DaggerTestBean注入成功了";@Injectpublic DaggerTestBean(){}public String showMessage(){return msg;}
}

在构造函数上添加@Inject注解

在需要依赖的类中生命对象:

public class DaggerTestActivity extends AppCompatActivity {@InjectDaggerTestBean mDaggerTestBean;private TextView mTvDagger;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_daggertest);mTvDagger = findViewById(R.id.tv_dagger);DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);Log.d("daggerTest", "msg: " + mDaggerTestBean.showMessage());}
}

并在声明的对象上添加@Inject注解,仅仅如此还不够

我们需要一个Module,和一个Component类

Module用来声明可以提供哪些实现,如下:

@Module
public class MainModule {}

这里暂时用一个空的添加了@Module注解的Module类

Component是注解器,链接依赖方和Module,如下:

@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {void inject(DaggerTestActivity daggerTestActivity);
}

添加了@Singleton和@Component注解,并指定了modules为MainModule.class,这里是要指明该注入器依赖和被依赖的范围,

需要的模块都建立好了,最后在需要依赖的地方DaggerTestActivity的oncreate中添加注入动作代码:

DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);

运行输出:

daggerTest: msg: DaggerTestBean注入成功了

这样简单的使用过程就完成了。

上边的例子是对Bean做了Inject处理,标识可被Module创建对象,也可以在Module中添加提供方法:

@Module
public class MainModule {@ProvidesDaggerTestBean provideTestBean(){return new DaggerTestBean();}
}

这样就不需要在Bean中添加Inject注解了。

Dagger2的原理简单分析

看下编译器做了什么,打开app/build/generated/ap_generated_sources/debug/out/com/modeng/aspro/下多了

DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);

追踪inject,发现逻辑还是挺清晰的,

DaggerMainComponent即为编译器自动生成的规则为Dagger+Component类名的类,看下其inject方法:

@Override
public void inject(DaggerTestActivity daggerTestActivity) {daggerTestActivityMembersInjector.injectMembers(daggerTestActivity);
}

调用了daggerTestActivityMembersInjector的injectMenbers方法,看下这个daggerTestActivityMembersInjector对象是什么:

private void initialize(final Builder builder) {this.daggerTestActivityMembersInjector =DaggerTestActivity_MembersInjector.create(com.modeng.voicecontrolpro.utils.DaggerTestBean_Factory.create());
}

在DaggerMainComponent的initialize方法中创建,其就是编译器生成的DaggerTestActivity_MembersInjector类,看下其injectMembers方法:

@Override
public void injectMembers(DaggerTestActivity instance) {if (instance == null) {throw new NullPointerException("Cannot inject members into a null reference");}instance.mDaggerTestBean = mDaggerTestBeanProvider.get();
}

这里有些熟悉的身影了,这里给DaggerTestActivity的mDaggerTestBean赋值了,mDaggerTestBean这个就是咱们添加注解需要注入的对象,继续看下mDaggerTestBeanProvider.get()

public DaggerTestActivity_MembersInjector(Provider<DaggerTestBean> mDaggerTestBeanProvider) {assert mDaggerTestBeanProvider != null;this.mDaggerTestBeanProvider = mDaggerTestBeanProvider;
}

DaggerTestActivity_MembersInjector在创建的时候给mDaggerTestBeanProvider赋值,继续跟踪

public static MembersInjector<DaggerTestActivity> create(Provider<DaggerTestBean> mDaggerTestBeanProvider) {return new DaggerTestActivity_MembersInjector(mDaggerTestBeanProvider);
}

来到了DaggerMainComponent类中:

private void initialize(final Builder builder) {this.daggerTestActivityMembersInjector =DaggerTestActivity_MembersInjector.create(com.modeng.voicecontrolpro.utils.DaggerTestBean_Factory.create());
}

继续看下DaggerTestBean_Factory的create方法,很明显这个是工厂方法:

creat方法拿到的是DaggerTestBean_Factory的实例,通过get方法,拿到创建好的DaggerTestBean对象,至此依赖对象和被依赖对象绑定,完成注入。

public enum DaggerTestBean_Factory implements Factory<DaggerTestBean> {INSTANCE;@Overridepublic DaggerTestBean get() {return new DaggerTestBean();}public static Factory<DaggerTestBean> create() {return INSTANCE;}
}

Dagger2的其它应用

上边讲的是基本用法了,现在来看下其它一些常用切比较复杂的场景:

1. 需要在不同的条件下获取不同的对象,这个时候用到@Named注解:

  1. 调整下DaggerTestBean:
public class DaggerTestBean {private String msg="DaggerTestBean注入成功了,是测试环境";public DaggerTestBean(){}public DaggerTestBean(String a){this.msg = a;}public String showMessage(){return msg;}
}
  1. 改变下Module:
@Module
public class MainModule {@Named("debug")@ProvidesDaggerTestBean provideTestBean(){return new DaggerTestBean();}@Named("release")@ProvidesDaggerTestBean provideTestBeanWithParams(){return new DaggerTestBean("DaggerTestBean注入成功了,是生产环境");}
}
  1. 注入时:
public class DaggerTestActivity extends AppCompatActivity {@Named("params")@InjectDaggerTestBean mDaggerTestBean;
  1. 输出:daggerTest: msg: DaggerTestBean注入成功了,是生产环境

2. Component依赖

添加一个Module:AMoudle

@Module
public class AModule {@Named("debug")@ProvidesDaggerTestChildBean provideTestBean(){return new DaggerTestChildBean();}@Named("release")@ProvidesDaggerTestChildBean provideTestBeanWithParams(){return new DaggerTestChildBean("DaggerTestChildBean注入成功了,是生产环境");}
}

提供的是DaggerTestChildBean:

public class DaggerTestChildBean {private String msg="DaggerTestChildBean注入成功了,是测试环境";public DaggerTestChildBean(){}public DaggerTestChildBean(String a){this.msg = a;}public String showMessage(){return msg;}
}

当一个Component同时需要MainModule和AModule提供对象时可以有不同的方式:

  1. Comopent注解中添加dependencies参数

    @Singleton
    @Component(modules = AModule.class,dependencies = MainModule.class)
    public interface MainComponent {void inject(DaggerTestActivity daggerTestActivity);
    }
    
  2. Module注解中添加include参数

    @Module(includes = AModule.class)
    public class MainModule {@Named("debug")@ProvidesDaggerTestBean provideTestBean(){return new DaggerTestBean();}@Named("release")
    @Provides
    DaggerTestBean provideTestBeanWithParams(){return new DaggerTestBean("DaggerTestBean注入成功了,是生产环境");
    }}
    
  3. Compoent注解中添加Module数组:

    @Singleton
    @Component(modules = {MainModule.class,AModule.class})
    public interface MainComponent {void inject(DaggerTestActivity daggerTestActivity);
    }
    

3. 当提供的对象是单利的时候,对应的Component也要是单利

这里要注意,单利是跟着被注入的对象的作用域走的,如果如果被注入到Activity中,作用域是Activity,换到其它Activity就重新创建对象了。

@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {void inject(DaggerTestActivity daggerTestActivity);
}
public class DaggerTestActivity extends AppCompatActivity {@Named("release")@InjectDaggerTestBean mDaggerTestBean;@Named("release")@InjectDaggerTestBean mDaggerTestBean1;
Log.d("daggerTest", "msg: mDaggerTestBean的hashCode = " + mDaggerTestBean.hashCode() + " mDaggerTestBean1的hashCode = " + mDaggerTestBean1.hashCode());

​ 输出:daggerTest: msg: mDaggerTestBean的hashCode = 224228315 mDaggerTestBean1的hashCode = 224228315

​ 如果定义在其它Activity:

​ 分别输出:

​ daggerTest: msg: mDaggerTestBean的hashCode = 224228315 mDaggerTestBean1的hashCode = 224228315

​ daggerTest: msg: mDaggerTestBean的hashCode = 12558410 mDaggerTestBean1的hashCode = 12558410

4. 实现真正的全局单利

既然单利跟着作用域走,那么在Application中的对象就应该是在整个app生命周期的单例了。

创建自定义Application,并创建MainCompoent对象:

public class MyApplication extends Application {private MainComponent mainComponent;@Overridepublic void onCreate() {super.onCreate();mainComponent = DaggerMainComponent.builder().mainModule(new MainModule()).build();}public MainComponent getMainComponent(){return mainComponent;}}

在Activity中拿到MainComponent对象并注入:

((MyApplication) getApplication()).getMainComponent().inject(this);
public class DaggerTestActivity extends AppCompatActivity {@Named("release")@InjectDaggerTestBean mDaggerTestBean;@Named("release")@InjectDaggerTestBean mDaggerTestBean1;
public class DaggerTest1Activity extends AppCompatActivity {@Named("release")@InjectDaggerTestBean mDaggerTestBean;@Named("release")@InjectDaggerTestBean mDaggerTestBean1;

输出:

singleton: onCreate: mDaggerTestBean = 224228315 mDaggerTestBean1 = 224228315

singleton: onCreate: mDaggerTestBean = 224228315 mDaggerTestBean1 = 224228315

可以看到,两个activity的对象都是一样的。

Dagger2的简单使用及基本原理相关推荐

  1. Dagger2的简单使用

    Dagger2可以更好的帮助我们解耦   不用担心对象或者属性在被生命周期持有导致的未释放 为什么要用Dagger2  举个例子 一般正常调用一个对象的方法是这样 public class A {pu ...

  2. 编译原理:简单词法分析器的设计与实现

    一.实验目的: 设计.编制并调试一个简单的c语言词法分析程序,加深对词法分析原理的理解 二.实验要求: 对单词的构词规则有明确的定义: 编写的分析程序能够正确识别源程序中的单词符号: 识别出的单词以( ...

  3. 依赖注入神器:Dagger2详解系列

    依赖注入神器:Dagger2详解系列 序言 Dagger2是啥 Dagger2是啥,Google告诉我们: Dagger is a fully static, compile-time depende ...

  4. 关于Dagger2的一些个人理解

    写作目的 现在基本上有一些规模的项目,都使用了Dagger2,也不是装13,个人感觉也的确是大势所趋,Dagger2的确有它的优势.借着手上的项目,学习了一下Dagger2,打算用在公司的项目中.今天 ...

  5. Dagger2的使用以及原理分析

    使用 Dagger2的使用说起来并不难,关键在于要掌握Dagger2的提供的几个注解及其意思. 环境搭建 在模块级的build.gradle文件中加入如下依赖: plugins {id 'com.an ...

  6. HNSW的基本原理及使用

    本文首发于:http://xzyin.top/hnsw/ 转载请注明出处:http://xzyin.top/ 相关系列文章可参考: <大规模向量相似度计算(一)--hnswlib的基本使用示例& ...

  7. 谷歌大脑联手Hinton提出SimCLR新框架,疯狂提升自监督学习性能 | 北邮毕业生一作...

    点上方蓝字视学算法获取更多干货 在右上方 ··· 设为星标 ★,与你不见不散 编辑:Sophia 计算机视觉联盟  报道  | 公众号 CVLianMeng 转载于 :新智元 BERT和T5之类的自然 ...

  8. LDA基本介绍以及LDA源码分析(BLEI)

    基本介绍: topic model,主题模型介绍:http://www.cnblogs.com/lixiaolun/p/4455764.html  以及 (http://blog.csdn.net/h ...

  9. C++中的虚函数(virtual function)

    1回顶部 一.简介 虚函数是C++中用于实现多态(polymorphism)的机制.核心理念就是通过基类访问派生类定义的函数.假设我们有下面的类层次: class A { public: virtua ...

  10. C++中重载与重写函数区别及虚函数(转载)

    C++中重载与重写函数区别及虚函数 C++中的虚函数(virtual function) 1.简介 虚函数是C++中用于实现多态(polymorphism)的机制.核心理念就是通过基类访问派生类定义的 ...

最新文章

  1. C/C++ 知识点---LIB和DLL的区别与使用(网摘)
  2. UA MATH571B 试验设计VI 随机效应与混合效应1
  3. 比较两个时间字符串的大小
  4. 【转】VS.NET2003 调试无法启动
  5. 二级Python 第三方库
  6. BugkuCTF-MISC题baby_flag.txt
  7. 震惊:selenium竟然不是自动化测试工具
  8. 《编程之美》第2刷勘误
  9. 四周实现爬虫系统(1)-抓取tripadvisor猫途鹰网站数据信息
  10. 快门光圈感光度口诀_只要三杯水,就能搞懂光圈/快门/感光度的关系!
  11. 《早秋客舍》赏析-[唐]杜牧古诗
  12. 星巴克的员工激励机制
  13. Java Swing扫雷游戏demo分享
  14. 登录失败:用户帐户限制。可能的原因包括不允许空密码,登录时间限制,或强制的策略限制。 ...
  15. ERROR 1819 (HY000): Your password does not satisfy the current policy requirements的解决方法
  16. 怎样判断驱动程序是否有通过WHQL认证获得微软数字签名
  17. java eventbus 原理_EventBus的简单使用与原理
  18. Postman安装(图文)
  19. Maven中的GroupID和ArtifactID指的是什么?
  20. 深入理解v4l2buf

热门文章

  1. 语音识别开源项目汇总
  2. c4d导出obj格式有破面_c4d导出obj格式错误怎么办 c4d导出obj格式教程
  3. 方兴未艾的语音合成技术与应用
  4. 大篆汉字对照表_篆书转换器软件下载(篆体字转换汉字对照表)
  5. 低版本浏览器不支持HTML5标签怎么解决?
  6. 富士施乐 DocuCentre-V 3065 打印机远程命令执行漏洞
  7. Uniapp 微信小程序登陆页面
  8. 工程量计算专用工具-支持灌注桩、搅拌桩、格构柱
  9. matlab自适应滤波,基于MATLAB与DSP的自适应滤波器设计与实现
  10. 锂离子电池性能测试软件,锂离子电池有什么性能测试设备?