Dagger2 使用正确姿势。_dagger2 同一个对象-程序员宅基地

Dagger2 使用正确姿势。

上一篇文章《[Dagger2 这次入门就不用放弃了](http://blog.csdn.net/u012943767/article/details/51897247》中介绍了Dagger2的一些显浅的使用方式,我觉得是非常适合入门Dagger2的傻瓜式讲解,后来发现有些内容讲的不够仔细,有些细节没有详细解释清楚。参考了以下三篇文章后,对之前的内容进行一些补充。

以上这三篇文章对于Dagger2的思路理得很清晰,并且对于Dagger2做出了一个抽象的概念讲解,本文的一些内容也是摘自以上文章。

没有看过《Dagger2 这次入门就不用放弃了》可能不利于阅读

本文的内容:

本篇的内容同样不涉及到Dagger2的内部原理,只是对上一篇文章做了一些知识的补充,从而能够更好的使用Dagger2

  • 理清思路,Dagger2的两种提供注入实例的方式
  • 为什么ActivityComponent要提供一个inject方法。
  • Scope的使用,如何实现单例?
  • Qualifier限定符的作用以及使用。
理清思路,Dagger2的两种提供注入实例的方式。

之前说的是提供注入实例的方式是通过编写Moudle,并且提供一些provideXXX()的方法,然后通过Component把这些对象进行注入。
其实在Dagger2中还有一种方式实现对象的注入,这种方式比较简单。假设我们需要注入一个A类的对象,我们只需要在A类的构造函数中添加@Inject注解即可,然后在Component中直接提供一个方法获取A的实例就行了。代码如下:


public class A{

    @Inject
    public A(){
    }
}


//在  XXXComponent 中

A getA();

然后在我们需要注入A对象的地方(Activity),使用Component调用getA()方法即可获得这个A对象。

说到这里,可能也会有些疑问,这里的A类是一个简单的对象,假如A需要在构造函数传入参数怎么办?其实原理和上一篇文章说的差不多,这些参数会根据依赖的Component或者当前Componentmodule中提供的provideXXX()方法来获取。

这里的Dagger2总共就有这两种方式提供依赖的注入。事实上,经过测试,Dagger2在遇到@Inject修饰的成员变量的时候,会先查找Component中是否有提供对象,找不到的情况下,才会去找包含有@Inject的构造函数。

整个Dagger2的依赖注入的过程如下:

步骤1:查找Module中是否存在创建该类的方法。
步骤2:若存在创建类方法,查看该方法是否存在参数
    步骤2.1:若存在参数,则按从**步骤1**开始依次初始化每个参数
    步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,
           看构造函数是否存在参数
    步骤3.1:若存在参数,则从**步骤1**开始依次初始化每个参数
    步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
为什么ActivityComponent要提供一个inject方法

首先经过我的测试,当我在DaggerActivity中对对某些需要注入的成员添加@Inject注解的时候,Dagger2就会生成一个DaggerActivity_MembersInjector的东西,这个是对成员变量进行注入的关键类,涉及到一些比较深入的内容,我们这里先不要深入探讨这里的运行机制。我们只需要知道当我们需要注入一些成员变量的时候,我们需要在ActivityComponent中提供一个方法:

void inject(DaggerActivity daggerActivity);

并且在初始化的时候调用这个方法,才能成功注入。至于这个方法inject是官方推荐的名称,我们可以不用这个,但是使用inject的话比较好理解吧。值得注意的一点是,这个方法的参数一定要准确,比如DaggerActivity需要注入,我们这里就需要些DaggerActivity,不能写成BaseActvity或者Activity,否则会注入失败。因为内部的原理是要对这个参数进行注入的,很显然在DaggerActivity中需要注入的内容在BaseActivity或者Activity中并不存在。

Scope的使用,如何实现单例?

这个迷之Scope也是有点难以理解,我们在哪里使用到了Scope呢。在我们的AppComponent中添加了一个注解为@Singleton@Singleton就是一个Scope,据说可以实现单例哟。。。难道这样就实现了单例模式?我刚刚开始是这样理解的。直到仔细的看了几遍这篇文章我才知道并不是这样的。

事实上@Sinleton中并没有创建单例的能力,那么AppComponent中提供的依赖注入是如何实现单例的呢。其实这个原理很贱单。

首先Module提供了创建实例的方法,接着AppComponent中对Module进行管理,最后AppComponent在自定义Applicaiton中被实例化了一次

这个实例化了一次是最重要的呀。仅仅被实例化了一次,那不就是单例么。就是这么简单呀。

可能有些童靴当时就不乐意了,那既然这样都已经实现了单例,那么这个@Singltop还要来何用?不是多此一举吗。

其实@Singletop还有有一些作用的,首先一方面能让你直面的了解到这是一个单例,其次这个@Singletop能够更好的管理ModlueComponent之间的关系。

Dagger2需要保证ComponentModule是匹配的,就需要用到这个注解。

为什么这样说,看过上一篇文章的人就会知道,我定义了一个ActivityScope,我之前的解释是说ActivityScope是为了对应Activity的生命周期(当时就很不理解,难道这个Scope真的这么有魔性,声明一个ActivityScope就能让提供的注入对象和Activity生命周期一致),很显然,这是错误的。为什么需要这个Scope呢?原因是因为我在AppComponent中是有@Singletop的,ActivityComponent中依赖了AppComponent,所以我们需要使用一个Scope来匹配他们之间的关系,不然就会在编译期间报错。并不是说ActivityScope能让实例和Activity生命周期一致。和Activity生命周期一致是因为ActivityComponent是在Activity中生成实例的。(具体Dagger2内部是如何保障这个的,并没有深入研究过)。

Qualifier 限定符的作用以及使用。

这也是一个很强大的注解,首先为什么需要用这么一个东西呢,之前说道过,在Module中的provide方法实际上是根据返回值来进行识别的。但是假设我需要根据不同的需求传入不同的构造参数的时候,如何区分呢?比如:一个Presenter,可能他有两个构造函数,分别对应不同的需求,这种情况下,provide方法的返回值都是Presenter,那么就需要使用Qualifier。具体怎么使用呢。

首先声明一个注解用@Qualifier修饰,然后在需要区别的地方添加就行了,下面是一个实例代码:

@Module
public class AppModule {
    
    private final App app;

    public AppModule(App app) {
        this.app = app;
    }

    @Provides
    @Singleton
    @ForApplication
    Context provideAppContext() {
        return app;
    }

    @Provides
    @Singleton
    Prefser providePrefser(@ForApplication Context context) {
        return new Prefser(context);
    }

    @Provides
    @Singleton
    AccountManager provideAccountManager(@ForApplication Context context) {
        return AccountManager.get(context);
    }

首先在provide中添加一个注解@ForApplicition,接着在需要使用这个Context的地方再次标示即可。这样假设有其他一些提供了ActivityContext的地方和这里发生冲突的时候,Dagger2也能准确找到这个ApplicaitonContext

总结

这里对Dagger的总体使用方式进行了一些补充,还有没有从源码的角度来理解Dagger2,下篇文章会结合Dagger2生成的代码进行讨论,只有认识了这个运行机制,我们才能运用得得心应手。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012943767/article/details/51941872

智能推荐

ps新手秒变大师必备的Ps插件全在这!(mac版本)_delicious retouch 5 mac-程序员宅基地

文章浏览阅读3k次。作为设计师Photoshop可谓神器,不论你是何种设计师多多少少都会用到它。随着时代的发展,对效率越来越注重,ps虽功能强大,但不是大神级别的炉火纯青,用起来还是比较浪费时间的,这是设计公司永远不会说的秘密。 今天专为使用Mac的同学们带来的是10款必备常用ps扩展插件合集!美工修图必备!1.Delicious Retouch 5.0 (DR5)白金版Delicious Retouch5 白金版 for mac(PS磨皮插件DR5)立即下载Delicious Retouch5 白金版 for mac_delicious retouch 5 mac

如何将图像从 React Native 上传到 Laravel API_react native launchimagelibrary 如何上传图片-程序员宅基地

文章浏览阅读410次。聚优影视TV双播盒子,内置多个资源接口,开源TVBOX制作!如今,开发人员同时处理前端和后端项目是很常见的。根据最近的一项开发人员调查,React Native 是全球最流行的用于构建跨平台移动应用程序的框架之一。Laravel 是一个 PHP Web 框架,具有优雅的代码结构,开发人员可以使用它来创建 REST API。Laravel 目前有71k 的 GitHub 星数,证明了它在开发者社区中的受欢迎程度。_react native launchimagelibrary 如何上传图片

sql函数--05---SQL----coalesce函数详解_sql coalesce-程序员宅基地

文章浏览阅读1.8k次,点赞4次,收藏5次。提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录coalesce函数背景:语法:COALESCE ( expression,value1,value2……,valuen)流程:举例:应用 1 :进行空值处理查询学生成绩,如果查不到,则赋值为0应用 2 :进行默认处理返回人员的“重要日期”if( , ,)函数也可以coalesce函数背景:主流数据库系统都支持COALESCE()函数, MYSQL、MSSQLServer、DB2、Oracle:这个函数主要用来进行空值处_sql coalesce

vue项目中 实现复制功能_vue 复制dom元素-程序员宅基地

文章浏览阅读1.5k次。vue使用插件vue 可使用 vue-clipboard 插件npm i vue-clipboard2 -S 安装插件在main.js 中引入import VueClipboard from ‘vue-clipboard2’Vue.use(VueClipboard)<el-input v-model="input" size="mini" placeholder="请输入内容"></el-input><el-button type="text" icon="_vue 复制dom元素

Spring Boot 2.0 设置Session过期时间_websocket 空闲过期时间-程序员宅基地

文章浏览阅读9.3k次,点赞3次,收藏3次。最近开发的一套基于WebSocket+Spring Boot2.0 的客服系统,测试完上线发现隔十分钟未操作websocket自动掉线,隔半个小时左右再刷新页面就跳转回登录界面了,才醒悟到自己没有加入心跳机制以及设置session过期时间,上网查了一下其他大牛的博客。在配置文件application.properties 加入了如下一行:以分钟(m)为单位,设置为150m后,放到一边测..._websocket 空闲过期时间

d435i 相机和IMU联合标定_aprilgrid 6x6 0.5x0.5 m (unscaled)-程序员宅基地

文章浏览阅读831次。一、前提我们已经对RGB摄像头和IMU进行了单独标定。参考之前博文。RGB标定IMUkalibr官方WIKI:Kalibr二、准备标定文件2.1 标定板yaml文件标定下载链接Aprilgrid 6x6 0.5x0.5 m (unscaled)Aprilgrid标定板yaml文件yamltarget_type: 'aprilgrid' #gridtypetagCols: 6 #number of apriltagstagRows: 6 _aprilgrid 6x6 0.5x0.5 m (unscaled)

随便推点

oracle 存储过程 带游标作为OUT参数输出_oracle存储过程 行变量入参-程序员宅基地

文章浏览阅读9.2k次。包中带过程 要自己定义一个type [cur_name] is ref cursor游标,返回的时候就直接 procedure AAA(变量名 out [cur_name])如此申明OUT变量 存储过程 用系统默认的 sys_refcursor 游标类型 定义变量就OK了 Sql代码 --PL/SQL Code (包中带过程) 过程带游标的OUT参数,返回游标(ref curs_oracle存储过程 行变量入参

AES-NI指令集-程序员宅基地

文章浏览阅读1.6k次。对于intel的AES-NI新指令集,需要i5处理器及以上的相关硬件支持.在编译时,可能会出现/usr/lib/gcc/x86_64-linux-gnu/4.8/include/wmmintrin.h:34:3: error: #error "AES/PCLMUL instructions not enabled"很显然,可以通过查其头文件,定位到#if !defined (__AES..._aes-ni指令集的下载与使用

Bug基础-程序员宅基地

文章浏览阅读131次。1.缺陷报告的定义软件不正常的错误或者是代码行错误等均衡成为缺陷2.缺陷的种类:功能不正常软件在使用上感觉不方便软件的结构未做良好规划提供的功能不充分与软件操作者的互动不良使用性能不佳未做好错误处理边界错误计算错误使用一段时间所产生的错误控制流程的错误在大数据量压力下所产生的错误在不同硬件环境下产生的错误版本控制不良导致的错误软件文档的错误3.将缺陷按照严重程度划分系统崩溃,严重,一般,次要,建议4.解决bug的优先级高,中,低5.按照测试种类分:逻辑功能类性_bug基础

macOS高端使用技巧_mac指标高级运用?-程序员宅基地

文章浏览阅读185次。Macos 的占有量不如 Windows,两者之间当操作方式也有很大的不同,当很多人熱悉 Windows 的操作之后,再接触 macos,觉得难上手,其实是习惯问题。如果你学习一些技巧,会觉得 macos 其实也不错,某些方面,甚至远远优于 Windows。很多人说 macos 这效率上会优于 Windows,这点必须承认,毕竟 macos 包括其平台下的软件,有很多的快捷键,并且感觉苹果也有意让大家多多利用快捷键。那么多的快捷键,并且 control 和 command 在使用上,没有一定的规律可循,导_mac指标高级运用?

金融风控_特征衍生案例代码实现_放款中数据分析_交费数据特征衍生-程序员宅基地

文章浏览阅读694次。对creat_dt做补全,用oil_actv_dt来填补 截取6个月的数据。构造变量的时候不能直接对历史所有数据做累加。否则随着时间推移,变量分布会有很大的变化。_交费数据特征衍生

排序算法基本介绍及python实现(含详细注释)_python选择排序详细写法与注释-程序员宅基地

文章浏览阅读1.1w次,点赞165次,收藏276次。对数组排序可以说是编程基础中的基础,本文对八种排序方法做简要介绍并用python实现。代码中注释很全,适合复习和萌新学习。这是刚入学自己写的,可能难免比不上标准的写法,但是懒得改了。文末会放和排序相关的基本拓展总结链接。看不明白可以看群里视频注意排序实现的具体方式,不要用局部变量,否则占空间太多,和空间复杂度不符。好,我们开始。选择排序选择排序(Selection sor..._python选择排序详细写法与注释

推荐文章

热门文章

相关标签