Dagger2依赖注入
前面我们做好学习准备接下来就要研究如何使用了,俗话说的好,一个东西需要先会用,然后才更好的学习原理。
一、导入Dagger2
在工程的build.gradle文件中添加android-apt插件(该插件后面介绍)
buildscript {
....
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
在app的中的build.gradle文件中添加配置
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.mahao.alex.architecture"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
compile 'org.glassfish:javax.annotation:10.0-b28'
}
android-apt是Gradle编译器的插件,根据其官方文档,主要两个目的:
- 编译时使用该工具,最终打包时不会将该插件打入到apk中。
- 能够根据设置的源路径,在编译时期生成相应代码。
二、写个Demo
这个就依照上篇的女孩依赖于一个男孩,这我们再加一个依赖就是父母(毕竟男人不一定靠的住^(* ̄(oo) ̄)^)。好了开始写
写一个Module类,管理上面的依赖。
@Module
public class GirlModule {
@Provides
public Boy provideBoy(){
return new Boy();
}
@Provides
public Parents provideParents(){
return new Parents();
}
}
写一个Component类,来连接Module和你的Girl。
@Component(modules = GirlModule.class)
public interface GirlComponent {
void inject(Girl girl);
}
到了这里不要急着往下写,先运行一下你的代码。(下面再说为什么)
好了,继续下一步,重写Girl类
public class Girl {
@Inject
Boy boy;
@Inject
Parents parents;
public Girl() {
DaggerGirlComponent
.builder()
.girlModule(new GirlModule())
.build()
.inject(this);
Log.d("Girl", "new Girl()");
}
}
首先我们可以看到在使用过程出现了很多注解:
- @Module:作为实例对象的容器。
- @Provides:标注能够提供实例化对象的方法。
- @Component:作为桥梁,注入对象的通道。
- @Inject:需要注入的方法
分析
我们可以看到在GirlModule 是用一个@Module注解的类,这是作为实例对象的容器,用于管理,里面的方法是使用@Provides注解,可以看出来其实就是给你提供依赖的方法。
我们知道了管理并提供依赖的类,那么我们就可以通过它来直接使用依赖。但是Dagger2为了解耦,提供了一个中介,@Component注解,这是作为桥梁将依赖和需求(girl)联系起来。
@Component(modules = GirlModule.class)
public interface GirlComponent {
void inject(Girl girl);
}
那么我们来看看@Component的官方文档。
* Annotates an interface or abstract class for which a fully-formed, dependency-injected
* implementation is to be generated from a set of .
说的是这个注解只能用于接口或者抽象类。将代码改成下面,输出也是一样的。
@Component(modules = GirlModule.class)
public abstract GirlComponent {
void inject(Girl girl);
}
还有 @Inject注解 就是使用的时候的注入方法。
@Inject
Boy boy;
上面的代码表示Boy 这个属性你不用像一般情况去初始化(boy= new Boy ()),它能给你自动寻找依赖。
但是这样就可以了么?当然是不行,你都没有和前面的联系其来。所以还需要如下代码:
DaggerGirlComponent
.builder()
.girlModule(new GirlModule())
.build()
.inject(this)
这里你就会看到一个你没有创建的类是,这个是由apt工具帮我们生成的类,但是是在编译时期生成代码,所以为什么前面要你们先运行下(我之前就是一头雾水,大部分人都说生成没说怎么生成,搞的我一度误解)
这里tip一下
在android-apt的文档中,也推荐使用这种方式。因为,编译时期生成代码的类库在运行期并不需要,那么将其分为两个库,(运行类库dagger)和(编译器生成代码类库(dagger-compiler)),那么在打包时,就不需要将dagger-compiler打入其中(用不到),减小APK 的大小。
DaggerGirlComponent实现了GirlComponent接口。
通过girlModule()将我们的依赖提供者传入,通过inject()将我们的Girl对象传入,这样就达到了中间人的目的。
package com.example.admin.dagger2.gg;
import dagger.MembersInjector;
import dagger.internal.Preconditions;
import javax.annotation.Generated;
import javax.inject.Provider;
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerGirlComponent implements GirlComponent {
private Provider provideBoyProvider;
private Provider provideParentsProvider;
private MembersInjector girlMembersInjector;
private DaggerGirlComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static GirlComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideBoyProvider = GirlModule_ProvideBoyFactory.create(builder.girlModule);
this.provideParentsProvider = GirlModule_ProvideParentsFactory.create(builder.girlModule);
this.girlMembersInjector =
Girl_MembersInjector.create(provideBoyProvider, provideParentsProvider);
}
@Override
public void inject(Girl girl) {
girlMembersInjector.injectMembers(girl);
}
public static final class Builder {
private GirlModule girlModule;
private Builder() {}
public GirlComponent build() {
if (girlModule == null) {
this.girlModule = new GirlModule();
}
return new DaggerGirlComponent(this);
}
public Builder girlModule(GirlModule girlModule) {
this.girlModule = Preconditions.checkNotNull(girlModule);
return this;
}
}
}
到这里基本的入门使用就知道。
这里想必还是一头雾水感觉不出有什么用处,不要着急,饭要一口一口吃,我们先了解使用,然后再慢慢一步一步了解。