Kotlin怎样使用魏延式的人才Android的Dagger2

3083人阅读
Android(18)
一、什么是dagger2?
Dagger2 是为Android和Java平台提供的一个完全静态的,在编译时进行依赖注入的框架。我们在做andriod开发的时候,一个Activity里面通常会实例化很多的类,才能使用这些的类中的方法和字段,通常,一个类很多Activity都会用到,我们就会在每个acitivity里面实例化该类。这样导致的问题就是,Activity会很依赖这些类,导致程序的耦合严重,不便于我们开发和维护。我们能有什么办法不去重新实例化这些类呢?要是这些类能直接在Activity中使用该多好。这时候就需要一个容器,我们将这些类放进这个容器,需要使用类的时候直接去容器取就好了,这样,我们就从依赖这个类到依赖这个容器了,实现了解耦。Dagger2正是为此而生,Dagger2框架就创造了这个容器,从此,我们的代码就变得更简洁了,程序间的耦合也减少了,程序变得容易开发和维护了。想想就有些小激动,是不是想赶快学会这门技术呢?
于是,我们去找度娘,我们去Google,发现关于dagger2的博客也有不少,但总是看得云里雾里,自己想入手写个demo,发现资料不足,最令人费脑的是,第一次看到dagger2的代码,第一反应是这是什么玩意儿,有点难以理解。但是dagger2能实现程序的解耦,想想还是蛮诱惑的,不弄懂dagger2心里就不踏实,弄懂dagger2后,以后写代码如鱼得水,想想还真有点小激动。
二、了解dagger2!
在我们准备实现dagger2的demo前,我们总想着要是能有一个关于dagger2的官方demo能在本地运行起来并能调试该多好啊,提前看下dagger2真正运行起来的效果,心里会踏实些,也会给自己多些信心去实现。dagger2目前由google维护,所以找demo这样的事情,我建议还是去google家找比较靠谱,至于平台嘛,当然是github啦。dagger2官方demo地址:&&。我们只需关注Android这块的介绍就OK啦。比如打开链接,你关注这里就好了,关于Android
Studio gradle的配置。
另外,Android 关于dagger2的官方demo位置在这里啦。
你可以把android-sample里面的代码download下来,复制到自己新建的android工程里面,运行看看哦!
三、运行google官方 dagger2 Demo!
1、dagger2 开发环境配置
1)Android Studio新建Android工程,配置project的build.gradle文件
ext.kotlin_version = '1.0.1-2'
classpath &org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version&
classpath &org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version&
2)配置app模块的build.gradle文件
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
compile 'com.google.dagger:dagger:2.2'
kapt 'com.google.dagger:dagger-compiler:2.2'
provided 'javax.annotation:jsr250-api:1.0'
3)同步改动的代码或Rebuild Project。这样,dagger2的开发环境就配置好了。
2、导入google官方dagger2 demo代码
1)将官方demo下的simple文件夹及里面的文件复制到工程里,你会发现这里可能报错
因为DaggerDemoApplication_ApplicationComponent文件是通过dagger2框架自动生成的,你需要重新Rebuild Project或是Make Project即可。
2)配置Manifest文件,配置自己的DemoApplication,修改默认启动Activity为HomeAcitivity
3)运行工程,你就会在日志栏里看到打印信息
Log.d(&HomeActivity&, locationManager.toString());
四、理解google官方dagger2 demo并尝试造轮子!
1、理解dagger2的几个注解
1)@Moudle 用Moudle标注的类是专门用来提供依赖的
2)@Provides 用Provides来标注一个方法,该方法可以在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注@Injection的变量赋值。@Provides通常和@Moudle配合使用,用来标注Moudle里面的方法
3)@Inject Inject主要有两个作用,一是使用在构造函数上,将相关类实例化提供依赖,二是使用在需要使用的变量上提供依赖
4)@Component Component一般用来标注接口,被标注了Component的接口在编译时会产生相应类的实例来作为提供依赖方和被需要依赖方的桥梁,把相关依赖注入其中
2、从demo中理解四个dagger2的注解关键字
1)我们先来看AndroidMoudle类
AndroidMoudle类使用了@Moudle关键字,类里面使用了@Provides关键字。说明AndroidModule类用来提供依赖,其中提供了获取application单例和获取定位管理类单例方法用来提供给需要使用的类依赖。
2)接着看DemoApplication类
其中使用了@Component和@Inject关键字。@Component中的moudles指定到AndroidMoudle类,接口中的方法分别依赖到HomeActivity、DemoActivity以及DemoApplication。说明ApplicationComponent接口在这里做了桥梁的作用,如果HomeActivity注入了该接口,则说明在HomeActivity中就可以用@Inject关键字使用AndroidMoudle中提供出来供依赖的方法或是单例类。同理,如果DemoApplication中注入了该接口,则说明在DemoApplication类中也可以使用AndroidMoudle中提供出来依赖的方法或是单例类。该例子的DemoApplication在onCreate的时候,通过component().inject(this)注入了该接口,所以它能@Inject
locationManager,从而使用该locationManager单例类。
注意:DaggerDemoApplication_ApplicationComponent是根据dagger2的代码框架自动生成的,当你完成AndroidMoudle类并做好了@Component连接,Rebuild Project或是Make Project即可生成该类。
3、开始造自己轮子吧
public class Car {
public Car(){
public String use(){
return &老司机开车咯&;
新建Driver类
public class Driver {
@Component(modules = {TransportModule.class})
public interface TransportComponent{
void inject(Driver driver);
void inject(MainActivity mainActivity);
TransportComponent transportC
public Driver(){
transportComponent = DaggerDriver_TransportComponent.builder()
.transportModule(new TransportModule())
transportComponent.inject(this);
public String driveCar(){
return car.use();
新建TransportMoudle类
public class TransportModule {
Driver provideDriver(){
return new Driver();
Car providerCar(){
return new Car();
MainAcitivity依赖
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvShow = (TextView) findViewById(R.id.tvShow);
Driver.TransportComponent transportComponent = DaggerDriver_TransportComponent.builder()
.transportModule(new TransportModule())
transportComponent.inject(this);
tvShow.setText(driver.driveCar());
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:37228次
排名:千里之外
原创:34篇
评论:20条
(1)(3)(2)(1)(3)(2)(1)(2)(7)(12)(1)android开发(116)
转自:/sunshine-anycall/p/5363301.html
依赖注入这个模式(模式已经用烂了,这里再烂一次)是用来给应用的各部分解耦的。使应用开发更加可扩展,更容易维护。通过本文你会学到如何使用Dagger2来处理依赖。
如果以对象需要另外的一个对象才能完成一个完整功能的话,那么这里就存在一个依赖。比如,悟空要用金箍棒才能三打白骨精,要筋斗云才能十万八千里。悟空有对金箍棒和筋斗云的依赖。你可以在悟空对象里初始化金箍棒,也可以用一个工厂方法批量生产金箍棒。使用依赖注入可以无需一个专门的类来初始化这些依赖对象。这样就实现了解耦。
本教程会使用最新的Dagger2(当前的版本是2.2)。这里是。你可以在这里找到最新的发布。
Android Studio是必须的。其他:
1. Dagger2 基础
注解讲解:
@Module这个annotation修饰的类专门用来提供依赖@Provides这个annotation修饰的方法用在Module类里@Inject用来annotation一个依赖(可以是构造方法、field或者一般的方法)@Component连接@Module和注入的桥梁
这些名词看起来非常抽象。下面稍微解释一下。依赖反射并没有什么神奇的地方。只不过是我们需要单独写初始化依赖的地方由其他的框架代替了。这个依赖关系也有我们常写的代码转移到了“配置文件”中。
在很久以前,依赖注入的框架就是这样处理依赖注入的:读取配置文件的依赖关系,然后用反射的方法初始化被依赖对象并赋值给调用依赖的对象。比如,我们之前在悟空类中初始化金箍棒:
public class Wukong {
public Wukong(){
this.jingubang = Jingubang();
后来有了使用配置文件的依赖注入(这里都是虚构的文件格式):
在悟空使用金箍棒的时候,依赖注入框架自动初始化好了金箍棒,并赋值给了悟空。
现在使用Dagger2。这里就有不得不说的牛X的地方了。因为是在Android里能用的资源没有后端那么多。尤其反射消耗比较大!所以Dagger为了满足移动开发节约资源的需要,没有使用反射实现依赖注入。而是在编译的时候同时生成依赖注入的相关代码。生成代码的根据就是前文中说明的那些注解(annotation)以及使用这些annotation的类、接口。
总结起来就一句话,Dagger把你需要在悟空类里写的金箍棒类的初始化代码都根据注解替你自动生成了!只不过这种生成的代码比明晃晃的使用new初始化的方法更加复杂一些。
Dagger2 开发步骤
把大象装冰箱一共分几步:
定义依赖和被依赖的对象的类,悟空类和金箍棒类。“悟空类”和“金箍棒类”的构造函数用@Inject注解修饰。,一般叫做XXXModule。。“悟空类”和“金箍棒类”对象。比如@Provides
Wukong provideWukong(){ return new Wukong(); }创建一个interface,并用@Component注解修饰。一般叫做XXXComponent。里面写一个注入方法:void
inject(Wukong wk);。这里Wukong只是一个例子。任何你准备要注入的类都可以代替上面参数的Wukong类。在需要注入的地方写@Inject的field。
最后,Dagger会根据上面的内容和最后的@Component接口生成一个DaggerXXXComponent的类型,使用这个类型来实现注入。上面的1到3步可以理解为依赖的配置。最后的XXXComponent代替古老的Reflect方式实现注入。
第一步的@Inject修饰的构造函数和`@Module`的`provideXXX`方法二者可以省略一个。
Dagger可以根据其中的任意一种配置创建依赖的对象。都写上等于有了双保险。
上文提到过多次。Dagger 2厉害的地方就在于这个库完全不用反射,而是用在编译期生成代码的方式实现的依赖注入。这个特点导致在Android Studio配置的时候需要做一些额外的工作。
这里假设你已经创建了一个新的Android应用项目。下面打开build.gradle文件,我们一步一步的来完成Dagger2的配置。
3. Android Studio的配置
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
为什么要加一个新的plugin呢?这个是为后面使用的kapt和provided提供支持的。gradle本身不支持这两个操作。
buildscript {
ext.kotlin_version = '1.0.1-2'
repositories {
mavenCentral()
dependencies {
classpath &org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version&
classpath &org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version&
dependencies {
compile 'com.google.dagger:dagger:2.2'
kapt 'com.google.dagger:dagger-compiler:2.2'
provided 'javax.annotation:jsr250-api:1.0'
dagger, 我们要用的正主。dagger-compiler, 用来生成代码。java.annotation, 提供Dagger意外的注解
最后,同步Gradle。
使用Dagger 2
下面就是Dagger一展身手的时候了。
首先,我们已经有悟空和金箍棒了。代码如下:
import javax.inject.I
public class Wukong {
JinGuBang jinGuB
public Wukong() {
public String useJinGuBang() {
return this.jinGuBang.use();
import javax.inject.I
public class JinGuBang {
public JinGuBang() {
public String use() {
return &user Jing gu bang&;
悟空对金箍棒有依赖,所以金箍棒属性有@Inject注解修饰。因为两个类都需要Dagger创建,所以在构造函数上都有@Inject注解。
第二步、创建@Module类
创建@Module注解的类,并在其中添加@Provides注解修饰的方法。这些方法创建被依赖的对象。
import dagger.M
import dagger.P
public class XiYouModule {
Wukong provideWukong() {
return new Wukong();
JinGuBang provideJinGuBang() {
return new JinGuBang();
@Singleton注解表明,这个被依赖的对象在应用的生命周期里只有一个实例。这个里的@Provides方法和前一步说到的@Inject注解的构造函数两个可以只写一个。
第三步、@Component接口,连接@Module和@Inject
@Module和@Provides方法提供了被依赖的对象。@Inject在@Component接口出现的地方则是指明了需要注入的地方(一般是一个field)。@Component接口就是用来把他们连接起来的。
import android.app.A
import javax.inject.S
@Component(modules = {XiYouModule.class})
@Singleton
public interface XiYouComponent {
void inject(Wukong wk);
void inject(Activity a);
其中inject()方法里使用的对象,就是包含@Inject的field的需要注入的对象。
在这个接口中也可以不用inject()方法,而使用provideXXX()方法后面会有更多介绍。
注意:@Component接口一定要在直接中指明@Module类型
第四步、使用@Component接口获取对象
经过前面的步骤,依赖和被依赖对象关系都已经配置好了。下面就来获取被依赖对象来注入依赖对象。
public class MainActivity extends AppCompatActivity {
private static final String TAG = &##MainActivity&;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView welcomeTextView = (TextView) findViewById(R.id.welcome_textview);
XiYouComponent xiYouComponent = DaggerXiYouComponent
.builder()
.xiYouModule(new XiYouModule())
xiYouComponent.inject(this);
welcomeTextView.setText(wukong.useJinGuBang());
首先主要到属性@Inject
W已经在MainActivity声明了。这里表明一个依赖关系:这个activity依赖于悟空,并准备注入悟空对象。
Dagger2会在编译器自动生成依赖注入的代码,所以在添加上面的代码之前需要编译一下。DaggerXiYouComponent就是Dagger根据我们的XiYouModule类生成的代码。
在这一步给DaggerXiYouComponent的builder添加XiYouModule的实例。如果这个Module只需要用到无参构造函数的话可以用一种省略用法:create()方法。可以简写为:
DaggerXiYouComponent
.builder()
.create();
Component接口的对象调用inject(this)方法之后注入即完成。所以可以直接使用@Inject
W属性来调用方法:welcomeTextView.setText(wukong.useJinGuBang());最后在activity中显示方法返回的文字。
运行代码,看看结果吧。
以上内容可以概括为:什么被依赖,就把什么放在@Module类里(或者什么被依赖,就给什么添加@Inject的无参构造函数)。什么有依赖(@Inject属性),就把什么放在@Component接口的inject()方法参数里。(或者有什么@Inject属性,就在@Component接口里provide什么对象)。这个概括不一定严密,但是基本用法全部包括了。
依赖注入是很有用的。以上的内容只是Dagger2依赖注入的一部分。各位读者还需要根据官方文档多加练习才能更好的理解依赖注入和Dagger的各种用法。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:76740次
积分:1199
积分:1199
排名:千里之外
原创:11篇
转载:183篇
(2)(3)(4)(4)(6)(13)(4)(10)(7)(2)(5)(5)(18)(7)(1)(2)(2)(2)(3)(1)(1)(1)(2)(2)(4)(2)(1)(1)(6)(2)(1)(6)(31)(11)(3)(10)(11)dagger2 让你爱不释手:终结篇 - 安卓 - 伯乐在线
& dagger2 让你爱不释手:终结篇
如果您对dagger2的概念,整个依赖注入框架还不清楚,可以先了解下我的前2篇文章:
这2篇文章也收到好多网友的好评和提问,谢谢大家的支持。我大概总结了下提的问题:
dagger2到底能带来哪些好处?
dagger2怎么使用?
因此我将结合这2点来进行本文的讲解。并且会有具体的sample。
dagger2到底有哪些好处?
咱们直奔主题:
增加开发效率、省去重复的简单体力劳动
首先new一个实例的过程是一个重复的简单体力劳动,dagger2完全可以把new一个实例的工作做了,因此我们把主要精力集中在关键业务上、同时也能增加开发效率上。
省去写单例的方法,并且也不需要担心自己写的单例方法是否线程安全,自己写的单例是懒汉模式还是饿汉模式。因为dagger2都可以把这些工作做了。
更好的管理类实例
每个app中的ApplicationComponent管理整个app的全局类实例,所有的全局类实例都统一交给ApplicationComponent管理,并且它们的生命周期与app的生命周期一样。
每个页面对应自己的Component,页面Component管理着自己页面所依赖的所有类实例。
因为Component,Module,整个app的类实例结构变的很清晰。
假如不用dagger2的话,一个类的new代码是非常可能充斥在app的多个类中的,假如该类的构造函数发生变化,那这些涉及到的类都得进行修改。设计模式中提倡把容易变化的部分封装起来。
我们用了dagger2后。
假如是通过用Inject注解标注的构造函数创建类实例,则即使构造函数变的天花乱坠,我们基本上都不需要修改任何代码。
假如是通过工厂模式Module创建类实例,Module其实就是把new类实例的代码封装起来,这样即使类的构造函数发生变化,只需要修改Module即可。
有个网友问过一个这样的问题,Module的构造函数也会发生变化,发生变化后,相应的new Module的类也发生变化,这就没有达到解耦的效果。首先解耦不是说让类之间或模块之间真的一点关系都没有了,解耦达到的目的是让一个类或一个模块对与自己有关联的类或模块的影响降到最低,不是说这种影响就完全没有了,这是不可能的。
解耦还有个好处,就是方便测试,若需要替换为网络测试类,只需要修改相应的Module即可。
项目中使用dagger2注意点
具体的代码就不讲了,,大家自行下载。这里重点说下dagger2对目标类进行依赖注入的过程,现在假设要初始化目标类中的其中一个依赖类的实例,那具体步骤就在下面:
步骤1:查找Module中是否存在创建该类的方法。
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从**步骤1**开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,
看构造函数是否存在参数
步骤3.1:若存在参数,则从**步骤1**开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤1:查找Module中是否存在创建该类的方法。步骤2:若存在创建类方法,查看该方法是否存在参数&&&&步骤2.1:若存在参数,则按从**步骤1**开始依次初始化每个参数&&&&步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束步骤3:若不存在创建类方法,则查找Inject注解的构造函数,&&&&&&&&&& 看构造函数是否存在参数&&&&步骤3.1:若存在参数,则从**步骤1**开始依次初始化每个参数&&&&步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
以上是dagger2进行的一次依赖注入的步骤,其实这个步骤是一个递归的过程,并且在查找类的实例的过程中Module的级别要高于Inject,这概念在讲过。
下面在说下注意的几点
一个app必须要有一个Component(名字可以是ApplicationComponent)用来管理app的整个全局类实例
多个页面可以共享一个Component
不是说Component就一定要对应一个或多个Module,Component也可以不包含Module
自定义Scope注解最好使用上,虽然不使用也是可以让项目运行起来的,但是加上好处多多。
好了关于dagger2的所有的概念知识点到此终于结束了,希望能帮助大家,与大家共勉,有问题可以随时与我沟通。
打赏支持我写出更多好文章,谢谢!
打赏支持我写出更多好文章,谢谢!
任选一种支付方式
关于作者:
可能感兴趣的话题
没有结合代码讲解 脑补还是有点难度
关于安卓频道
安卓频道分享Android开发文章,精选工具和安卓相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线5503人阅读
Android(16)
Dagger2(1)
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
现在Dagger2在项目中的使用越来越多,Dagger2是Dagger的升级版本,Dagger没有使用过,但是本篇说的是Dagger2,主要讲解的是Dagger2是如何使用的。对了,忘了说Dagger其实是一个依赖注入的框架。
什么是依赖注入
依赖注入是一种面向对象的编程模式,它的出现是为了降低耦合性,所谓耦合就是类之间依赖关系,所谓降低耦合就是降低类和类之间依赖关系。可能有的人说自己之前并没有使用过依赖注入,其实真的没有使用过吗?当我们在一个类的构造函数中通过参数引入另一个类的对象,或者通过set方法设置一个类的对象其实就是使用的依赖注入。
通常依赖注入有以下几种方式
通过接口注入
interface ClassBInterface {
void setB(ClassB b);
public class ClassA implements ClassBInterface {
ClassB classB;
void setB(ClassB b) {
通过set方法注入
public class ClassA {
ClassB classB;
public void setClassB(ClassB b) {
通过构造方法注入
public class ClassA {
ClassB classB;
public void ClassA(ClassB b) {
通过注解的方式注入
public class ClassA {
ClassB classB;
public ClassA() {}
下面我们就来说说如何通过Dagger2来实现依赖注入吧。
引入Dagger2
添加apt插件
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
添加依赖(在build.gradle中添加如下代码)
apply plugin: 'com.android.application'
//添加如下代码,应用apt插件
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
//java注解
compile 'org.glassfish:javax.annotation:10.0-b28'
使用Dagger2
添加完Dagger的依赖后我们如何在项目中使用Dagger呢?
在项目中绝大多数的使用都是Dagger结合MVP架构使用的,在MVP中使用是非常典型的降低耦合的使用。不懂MVP的可以。
本篇文章中的示例是一个简单的登陆功能的示例,代码沿用上篇讲解MVP的登陆代码,,该示例采用MVP架构设计通过Dagger2进行解耦合,下面就来看看如何使用吧。
在使用Dagger2前我们最好简单的了解一下MVP,主要是为了理解本篇中的代码。简单了解MVP即使不会写MVP也可以看的懂本篇的代码。
为什么要选择在MVP模式中使用Dagger2呢?因为在MVP模式中Activity持有presenter的引用,同时presenter也持有view的引用,这样便于更新UI界面,这样Activity就和presenter仅仅的耦合在一起了,
而Dagger2是依赖注入框架就是解耦合的,所以子MVP中使用Dagger2也就再好不过了。
在上篇文章讲解MVP时我们可以明显的看到如下代码
public class LoginActivity extends AppCompatActivity implements ILoginView,View.OnClickListener{
private Button mL
private Button mC
private EditText mN
private EditText mPassW
ILoginPresenter loginP
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLogin = (Button) findViewById(R.id.btn_login);
mClear = (Button) findViewById(R.id.btn_clear);
mName = (EditText) findViewById(R.id.et_name);
mPassWord = (EditText) findViewById(R.id.et_password);
mLogin.setOnClickListener(this);
mClear.setOnClickListener(this);
loginPresenter = new LoginPresenterCompl(this) ;
在上述代码中可以看到activity持有了presenter的引用并且创建了该对象,但是如果presenter的构造函数发生改变则这里也需要改变,其实所有和presenter构造函数相关的代码都要改变。
但是如果我们使用Dagger2依赖框架该如何使用呢?请看下面代码
activity中的代码
public class LoginActivity extends AppCompatActivity implements ILoginView,View.OnClickListener{
..........
LoginPresenterCompl loginP
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLogin = (Button) findViewById(R.id.btn_login);
mClear = (Button) findViewById(R.id.btn_clear);
mName = (EditText) findViewById(R.id.et_name);
mPassWord = (EditText) findViewById(R.id.et_password);
mLogin.setOnClickListener(this);
mClear.setOnClickListener(this);
DaggerMainComponent.builder().mainModule(new MainModule(this)).build().inject(this);
LoginPresenterCompl中的代码
public class LoginPresenterCompl implements ILoginPresenter {
private ILoginView loginV
public LoginPresenterCompl(ILoginView view){
loginView =
user = new User("张三","123456") ;
只有上述两个注解还无法完成依赖注入,还需要如下两个新增类
新增的MainModule类
public class MainModule {
private final ILoginV
public MainModule(ILoginView view){
this.view =
ILoginView provideILogView(){
新增的MainComponent接口
@Component(modules = MainModule.class)
public interface MainComponent {
public void inject(LoginActivity activity) ;
通过直接注解和上述两个接口类即可完成Dagger2的依赖注入。
在LoginActivity中是通过
DaggerMainComponent.builder().mainModule(new MainModule(this)).build().inject(this)
完成依赖注入的。
看完上面的代码后,一脸的懵逼,WTF(what the fuck),这TM是什么,这么复杂,还不如之前的简单呢,新增了两个类还有这么多代码,得不偿失呀!
同志们,如果你们第一眼看到后是这样想的话,说明和我想的一样,呵呵。每一个刚接触Dagger2的人可能都会这样想,因为我们只看到了表面。
不错,表面上我们是多了一个类和接口也多了很多代码,但是这样的组合其实是可以理解的。因为通常简单的代码具有耦合性,而要想降低这样的耦合就需要其他的辅助代码,其实少代码量和低耦合这两者并不能同时兼顾,古人云:鱼和熊掌不可兼得。我们作为堂堂聪明绝顶的程序猿怎么可能会输给古人呢。
好!下面来认真讲解Dagger2是如何完成依赖注入的。
首先我们来看看LoginActivity代码
LoginActivity中有这么一段代码
LoginPresenterCompl loginPresenter ;
同样在LoginPresenterCompl中也有这么一段代码
public LoginPresenterCompl(ILoginView view){
loginView =
user = new User("张三","123456") ;
之所以挑出这两段代码是因为它们都添加了@Inject注解。
在LoginActivity中其实只有这么一句提到loginPresenter,在接下来的代码中并没有对其进行初始化。
那loginPresenter是如何进行初始化的呢(此处注意添加@Inject注解的变量不能被private修饰)?
直观上我们可以这样理解,被@Inject注解的代码存在某种联系,当代码执行到@Inject的时候程序会自动进入到这个类的构造方法中,如果正巧这个构造方法也被@Inject修饰了,那么系统就会帮我们自动创建对象。
这只是表面的理解,这其中肯定还有很多我们没有看到的“猫腻”。这俩不会无缘无故的有联系,肯定还有第三者,通过这个第三者这两个被@Inject注解修饰的代码才会产生联系。
这个第三者是谁呢?自然的我们就会想到我们添加的这个类和接口。
首先我们来分析MainComponent接口
@Component(modules = MainModule.class)
public interface MainComponent {
public void inject(LoginActivity activity) ;
MainComponent是一个接口(也可以是一个抽象类),在这个接口中我们定义了一个inject()方法,其中参数是LoginActivity对象,同时MainComponent还被@Component注解着,注解中modules的值是MainModule.class,这个内容会在接下来的地方进行说明,暂时先放一放。
此时在Android studio中,如果我们rebuild的一下项目就会有新的发现。在项目的build/generated/source/apt/debug/项目包名/dragger目录下生成对应的包其中包含DaggerMainComponent类,这个类名其实不是固定的,是根据我们上面写的MainComponent,加了Dagger前缀生成的DaggerMainComponent。
其实在这个时候我们就已经完成了present的依赖注入。
DaggerMainComponent.builder().mainModule(new MainModule(this)).build().inject(this)
中我们看到还有一个MainModule,这个是我们自己创建的一个类
MainModule代码如下
public class MainModule {
private final ILoginV
public MainModule(ILoginView view){
this.view =
ILoginView provideILogView(){
我们可以看到这个类被@Module注解修饰,内部有一个ILoginView的变量和一个构造方法还有一个被@Provides修饰的provideILogView方法。
看到这还是一脸懵逼,这个类是干嘛的?
在MainComponent接口中我们看到这么一个注解@Component(modules = MainModule.class),这里用到了MainModule,可见MainComponent需要MainModule一起才能完成工作。
其实这个类我们可以理解成提供参数的,也就是提供参数依赖的,如何理解呢?
在MainModule中我们为什么要提供ILoginView类型的对象?为什么不是其他的呢?
这是因为LoginPresenterCompl的构造函数需要这么一个参数,所以我们在这里提供这么一个相同的参数,并通过被@Provides注解修饰的方法将其返回出去,如果LoginPresenterCompl还需要其他的参数,同样我们也可以在这里添加对应类型的参数然后通过另一个被@Provides注解修饰的方法返回出去。
在MainComponent接口中提供的inject()方法的参数是LoginActivity,这个参数的含义是LoginPresenter要在什么地方注入。
了解了各个类的功能后我们来总结一下
@Inject 程序会将Dagger2会将带有此注解的变量或者构造方法参与到依赖注入当中,Dagger2会实例化这个对象
@Module 带有该注解的类需要对外提供依赖,其实就是提供实例化需要的参数,Dagger2在实例化的过程中发现一些参数,Dagger2就会到该类中寻找带有@Provides注解的以provide开头的需找对应的参数
@Component 带有该注解的接口或抽象类起到一个关联桥梁的作用,作用就是将带有@Inject的方法或对象和带有@Module的类进行关联,只有通过该接口或抽象类才可以在实例化的时候到带有
@Module中类中去寻找需要的参数,也就是依赖注入。
OK,下面我们来捋捋思路。
1、在这个示例代码中,LoginActivity中需要LoginPresenterCompl,所以在LoginActivity中定义了该对象并且通过@Inject将其注解,同时到LoginPresenterCompl的构造方法中也通过@Inject将其注解,
表明这些是需要依赖注入的。
2、因为在LoginPresenterCompl的构造方法需要ILoginView类型的参数,所以需要通过依赖将获取这些参数,所以就需要带有@Module注解的类用于获取需要的参数,
在@Module注解的类中通过被@Provides注解的以provide开头的方法对外提供需要的参数,一般而言有几个参数就需要有几个带有@Provides的方法。
3、此时还需要一个桥梁将两者联系到一起,带有@Component的接口或抽象类就起到这个桥梁的作用。注解中有一个module的值,这个值指向需要依赖的Module类,同时其中有一个抽象方法
inject(),其中的参数就是我们需要在哪个类中实例化LoginPreserentCompl,因为我们需要在LoginActivity中实例化,所以参数类型就是LoginActivity类型。
然后在Android studio中rebuild我们的项目,就会生成DaggerMainComponent类,通过
DaggerMainComponent.builder().mainModule(new MainModule(this)).build().inject(this)
完成我们需要的依赖注入。
可能我们通过上面的讲解,知道了如何使用Dagger2了,也知道具体的流程了,但是可能还会有些疑惑,为什么?Dagger2是如何通过一些接口和类就完成依赖注入的?
在此声明,别着急,知道如何使用这只是第一步,在下一篇文章中将会讲解Dagger2实现依赖注入的原理。敬请期待!!!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:22443次
排名:千里之外
原创:22篇
评论:25条
(1)(1)(5)(2)(1)(5)(3)(1)(1)(2)

我要回帖

更多关于 怎样使用共享的打印机 的文章

 

随机推荐