您的位置 首页 新闻

dagger2学习入门

准备工作 1.在工程根目录的build.gradle引入apt插件 classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.…

准备工作

1.在工程根目录的build.gradle引入apt插件

classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’

整体文件:

// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath ‘com.android.tools.build:gradle:2.2.0-alpha1’ classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’ // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }

2.在app目录下的build.gradle加上一行

apply plugin: ‘com.neenbedankt.android-apt’

dependencies下面加上:

apt ‘com.google.dagger:dagger-compiler:2.2’ provided ‘org.glassfish:javax.annotation:10.0-b28’ compile ‘com.google.dagger:dagger:2.2’

别忘了加入lint warning

lintOptions { warning ‘InvalidPackage’ }

整体文件:

apply plugin: ‘com.android.application’ apply plugin: ‘com.neenbedankt.android-apt’ android { compileSdkVersion 23 buildToolsVersion “23.0.3” defaultConfig { applicationId “com.iiseeuu.dagger2demo” minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName “1.0” testInstrumentationRunner “android.support.test.runner.AndroidJUnitRunner” } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’ } } lintOptions { warning ‘InvalidPackage’ } } dependencies { compile fileTree(include: [‘*.jar’], dir: ‘libs’) compile ‘com.android.support:appcompat-v7:23.4.0’ compile ‘com.android.support.constraint:constraint-layout:1.0.0-alpha1’ testCompile ‘junit:junit:4.12’ androidTestCompile ‘com.android.support.test.espresso:espresso-core:2.2.2’ androidTestCompile ‘com.android.support.test:runner:0.5’ androidTestCompile ‘com.android.support:support-annotations:23.4.0’ apt ‘com.google.dagger:dagger-compiler:2.2’ provided ‘org.glassfish:javax.annotation:10.0-b28’ compile ‘com.google.dagger:dagger:2.2’ compile ‘com.google.code.gson:gson:2.7’ }

没有更多开场白,直接说下我对它的理解。

Dagger2 是一个Android依赖注入框架。而android开发当前非常流行的非MVP模式莫属了,Dagger2的目标便是将MVP中的V P 进一步解耦,达到模块化最大的解耦,使得代码更容易维护。

举个栗子:有个A对象 B对象 和C对象,如果C对象创建需要A和B,那么我们是不是需要构造里面传入参数A和参数B,然后在使用的地方如下写个代码:

C c = new C ( new A () , new B ());

如果我们使用了Dagger2时候,我们就不需要管这些了,只需要关联住能提供创建A 和 B的地方 ,然后在需要C的地方写下:

@Inject C c ;

然后在这个类的初始化地方进行注入即可。 我们初步来看,会发现Dagger2优势不大,没什么吸引人的,那么请你静下心来,看完再得出结论。

闲话休叙,我们来直接上代码:(常规写法)

#1 编写一个类:

public class Test3 { public Test3 () { } }

#2 使用的地方

public class MainActivity extends AppCompatActivity { Test3 test3 ; @Override protected void onCreate ( Bundle savedInstanceState ) { //….. test3 = new Test3 (); } }

如果我们改为使用Dagger2的方式的话,则可以写成如下方式:

#1 创建一个类

使用了注解方式,使得Dagger2能找到它。

public class Test3 { //这里可以看到加入了注解方式 @Inject public Test3 () { } }

#2 新增一个对象:

@Singleton //用这个标注标识是一个连接器 @Component () public interface MainActivityComponent { //这个连接器要注入的对象。这个inject标注的意思是,我后面的参数对象里面有标注为@Inject的属性,这个标注的属性是需要这个连接器注入进来的。 void inject ( MainActivity activity ); }

#3 调用的地方改为:

public class MainActivity extends AppCompatActivity { //加入注解,标注这个test3是需要注入的 @Inject Test3 test3 ; @Override protected void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ); setContentView ( R . layout . activity_main ); //使用组件进行构造,注入 DaggerMainActivityComponent . builder (). build (). inject ( this ); }

这是最简单的一种使用了。首先我们看到,第一印象是我去,这个更复杂了啊。我只能说确实,因为这个是它对的最基础的使用,看起来很笨拙,但是当它在大型项目里面,在依赖更多的情况下,则会发生质的飞跃,会发现它非常好用,并且将你需要传递的参数都隐藏掉,来实现解耦。

我先说下Dagger2的注释思路:关键的点是@Component,这个是个连接器,用来连接提供方和使用方的,所以它是桥梁。它使用在组件里面标记使用的Module(标记用到了哪个Module,主要是看使用方需要哪些对象进行构造,然后将它的提供方@module写在这里) 然后我们写入一个void inject(MainActivity activity); 这里后面的参数,就是我们的使用方了。如此一来,我们在使用的地方,使用类似这种方式(DaggerMainActivityComponent.builder().build().inject(this);)的动作,将使用方类里面的标记 为@Inject的类初始化掉,完成自动初始化的动作。

结构如下:

为了更好的来学习它,我们来依次看看各种使用情况。

#1 常规使用方法

直接感受下,如何?

#2 带一个参数的效果

我们来看一个代码段,当我们创建两个实例的时候,发现地址是独立的。

如果我们想要一样的地址呢?加上一句话,具体如下:

效果便是两个共用实例啦。

#3 换种经常使用的方式

将提供的构造,放入@module里面,具体效果如下:

去掉标记的@singleton后

效果变成独立的啦

#4 依赖一个组件的时候

有时我们需要依赖一个组件,这个最常见的用法是,我们App实例里面提供了比如获取sharepreference的实例,和比如现在代码里面的LocationManager的实例,我们Activity里面需要这些实例,我们该如何来做呢?看效果: 1:一个AndroidModule 模块标记

这个模块属于AndroidcationComponent 组件里面

这里有个关键点,就是子组件需要这个里面的某个实例的时候,这里需要使用一个接口,将需要的实例做一个返回动作。这里是LocationManager这一行。

我们的子组件的代码如下:

对应的Cmodule代码如下:

再来看下Test3的代码当前情况:

使用的地方:

细心的你会发现这里多了一个注释了,@PerActivity,它是个什么鬼呢?

这里我们看到它是使用了@Scope的一个注释,这个注释的意思就是作用域,在作用域内保持单例,可以直接理解为单例即可。 为什么要新增一个呢,主要是因为各个组件需要独立出来,因此如果是依赖关系,则需要各自在不同的注释作用域里面。 我们来看下在Cmodule里面,加上@perActivity注释后的效果:

如果去掉呢?

我们突然发现,它和单例的注释起的作用一样啊。so。。。是不是发现什么啦。

因此我们得出一个结论,这里@Singleton 就是一个普通的作用域通道,使用了作用域@Scope注释的代码,会变成单例模式。为了验证我们的思路,作如下测试:

我们将之前的@Singleton用新建的这个替换掉,验证两次的生成代码,发现一模一样,一模一样,一模一样,so。。。 就是这个样子啦。

#5 自定义一个标记 为什么要自定义标记呢?这个标记不是使用@Scope注释的哦,是使用@Qualifier 标记的,它的目标是,为了区分如果同时返回类型一样,比如构造男孩,女孩的基本属性,性别和名字时候,获取男孩和女孩都是一个对象,我们该如何区分呢,这个就是关键啦。说这么多,真心很烦,直接栗子来啦。

这里稍安勿躁,先来看相同效果的另一个注释,@Name,这个是Dagger2自带的一个让区分,效果如下:

这里@Name可以简单的一个使用方式,就是它不是区分对象,而是限制使用时候必须加入这个注释,否则报错,目的就是让使用者注意是否使用正确了。

我们使用自己的注释再来一遍:

对比两种方式,我们发现使用@Name的时候,后面的注释名字会敲错,而我们第二种方式呢,则不会耶,so。。。

我们看下自定义的标记,作为限制出错,让强制标注的例子。

#6 子组件(公共组件) 这个出现的目的是为了如果有一个组件,是每次创建实例提供给别人,而恰好其他组件(有多个)里面有需要它,如果只有一个,我们就用依赖搞定啦。那么它就可以定义成子组件,谁需要在谁的组件里面加一下,具体看例子:

#7 懒加载方式

#8 多个绑定方式

####1 第一种方式

####2 第二种方式

这里需要注意的就是,在组件里面加入多个绑定的时候,module的里面必须要有一个是@IntoSet 这个作为第一个标记,否则会出错,可以多个@IntoSet标记。

如果是列表类型的,则使用@ElementsIntoSet就ok了。

#9 终极boss ,Map方式

再加一点,生成的代码位置在\dagger2Demo\app\build\generated\source\apt\debug\com\xm\dagger2demo,可以直接看生成代码,更好理解

如上,写完啦。。

回到开始地方

实战地方,可以参照 https://github.com/gzsll/TLint 来阅读啦,收工。

参考链接

dagger 2 详解 – 简书

luxiaoming/dagger2Demo: 删减了很多东西了,主要是做教程实时修改了。欢迎 star fork

本文来自网络,不代表Xnewv立场,转载请注明出处:https://xnewv.com/2303.html

为您推荐

联系我们

联系我们

18873343099

在线咨询: QQ交谈

邮箱: [email protected]

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部