一,简介
Dagger2是Dagger1的分支,由谷歌公司接手开发的,Dagger2中没有再使用反射机制,而是使用派遣方法,自动生成如同自己手写的代码,好处是:第一,谷歌声称提高了13%的效率;第二,代码的调试变得更简单,缺点是缺乏灵活性。
二,接入
在项目的gradle文件中添加
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
在app的gradle文件中添加插件
apply plugin: 'com.neenbedankt.android-apt'
添加依赖
apt 'com.google.dagger:dagger-compiler:2.0'
compile 'com.google.dagger:dagger:2.0'
三,使用
首先了解一下dagger2中的几个注解:
@Inject,该注解有两个作用,标记变量,表示改变量有Dagger2容器提供,不需要自己初始化;标记构造函数,表示该类可以由Dagger2在需要的时候找到该构造方法,并提供该类的实例。
@module,标注用于提供需要注入的实例的类,当我们要提供第三方的依赖时,使用Inject注解类的构造函数很明显不现实,这时就可以使用这个注解,在module中提供。
@Provides,使用在用@module标注的类里面,告诉dagger2来这里找依赖。
@Component,用于标注接口,用来连接依赖提供者和依赖需求者。
@Qulifier,用于自定义注解,主要作用是当我们提供多个类型相同的依赖,可以用该注解区分。
@Scope,用于自定义注解,主要用于实现单例。
@Singleton,该注解就是通过@scope定义的注解,一般用于提供全局单例。
事件出真知,我们以汽车和引擎为例
案例1
引擎类,依赖提供
public class Engine {
@Inject
public Engine() {
}
public void start(){
System.out.print("引擎发动了");
}
}
汽车类,依赖需求
public class Bus {
@Inject
Engine engine;
public Bus(){
DaggerBusComponent.builder().build().inject(this);
}
}
@component标注类,相当于注入器,把Engine对象注入到Bus对象中,注意在该类写好后需要rebuild一下,否则不会生成上面的DaggerBusComponent类
@Component
public interface BusComponent {
void inject(Bus bus);
}
测试类,测试
public class TestMain {
public static void main(String args[]) {
new Bus().engine.start();
}
}
运行之后,如愿打印出信息,那我们就来分析一下,这个简单的例子是怎么实现依赖注入的呢?
四,源码分析
这里一共涉及到三个类,DaggerBusComponent,Bus_MembersInjector,Engine_Factory
public final class DaggerBusComponent implements BusComponent {
private MembersInjector<Bus> busMembersInjector;
private DaggerBusComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static BusComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.busMembersInjector = Bus_MembersInjector.create(Engine_Factory.create());
}
@Override
public void inject(Bus bus) {
busMembersInjector.injectMembers(bus);
}
public static final class Builder {
private Builder() {
}
public BusComponent build() {
return new DaggerBusComponent(this);
}
}
}
Bus_MembersInjector,注入类
public final class Bus_MembersInjector implements MembersInjector<Bus> {
private final Provider<Engine> engineProvider;
public Bus_MembersInjector(Provider<Engine> engineProvider) {
assert engineProvider != null;
this.engineProvider = engineProvider;
}
public static MembersInjector<Bus> create(Provider<Engine> engineProvider) {
return new Bus_MembersInjector(engineProvider);
}
@Override
public void injectMembers(Bus instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.engine = engineProvider.get();
}
public static void injectEngine(Bus instance, Provider<Engine> engineProvider) {
instance.engine = engineProvider.get();
}
}
Engine_Factory,看名字也能看出来是专门负责产生对象的工厂类
public final class Engine_Factory implements Factory<Engine> {
private static final Engine_Factory INSTANCE = new Engine_Factory();
@Override
public Engine get() {
return new Engine();
}
public static Factory<Engine> create() {
return INSTANCE;
}
}
首先看Dagger2给我们生成的DaggerBusComponent类
我们一步一步往下看
第一步,在我们构造DaggerBusComponent对象是会调用initialize(builder)方法,该方法会创建两个对象Bus_MembersInjector,Engine_Factory;
在Engine_Factory.create()中,会直接返回Engine_Factory单例对象,在Bus_MembersInjector.create()方法,把刚创建的Engine_Factory对象作为成员变量,并初始化DaggerBusComponent中的busMembersInjector成员变量,看到这里还是只知道其中类的关系,还是不知道到底怎么依赖,怎么注入的,别着急,慢慢往下看;
第二步,在调用Bus类中调用DaggerBusComponent的inject(Bus bus),真正调用的是Bus_MembersInjector的inject(),接下来就是关键代码instance.engine = engineProvider.get();这里,直接把engine对象赋值给bus对象的engine变量,这个engine对象来源于Engine_Factory类,而且这个对象是直接由Engine_Factory直接new出来的,至此,该案例分析完毕,哈哈,仰天大笑出门去,我辈岂是蓬蒿人。
这个非常简单的一个例子,如果我们依赖的对象的构造函数需要传参数,或者更复杂的该参数是另一个依赖的对象,接下来,分析一个更复杂的例子
案例2
我们还是以汽车和引擎为例,只不过这次我们的引擎的构造函数需要传入齿轮gear,并且齿轮的构造函数需要传入型号参数
一共有6各类
齿轮类Gear
public class Gear {
private String code;
public Gear(String code) {
this.code=code;
}
public void sayCode(){
System.out.print("齿轮的型号是:"+code);
}
}
引擎类Engine
public class Engine {
Gear gear;
public Engine(Gear gear) {
this.gear=gear;
}
public void start(){
gear.sayCode();
}
}
汽车类
public class Bus {
@Inject
Engine engine;
public Bus(){
DaggerBusComponent.builder().busModule(new BusModule()).build().inject(this);
}
}
BusModule,用来提供依赖
@Module
public class BusModule {
@Provides
Engine provideEngine(Gear gear){
return new Engine(gear);
}
@Provides
Gear provideGear(){
return new Gear("G型号齿轮");
}
}
Component,链接依赖需求与依赖提供
@Component(modules ={BusModule.class} )
public interface BusComponent {
void inject(Bus bus);
}
测试类不变
public class TestMain {
public static void main(String args[]) {
new Bus().engine.start();
}
}
结果输出如下
齿轮的型号是:G型号齿轮
在这个例子中,我们使用到了@module,基本逻辑和上面类似,我们重点来看看@module是怎么起作用的,以及Engine中的Gear对象是怎么注入进去的,废话不多说,下面分析源码
首先调用的是DaggerBusComponent中的initialize()方法
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideGearProvider = BusModule_ProvideGearFactory.create(builder.busModule);
this.provideEngineProvider =
BusModule_ProvideEngineFactory.create(builder.busModule, provideGearProvider);
this.busMembersInjector = Bus_MembersInjector.create(provideEngineProvider);
}
在改方法中会产生三个分别类型为Provider<Gear>,Provider<Engine>,MembersInjector<Bus>的成员变量对象,其中Provider<Gear>类型对象包含BusModule对象,Provider<Engine>类型对象包含BusModule对象以及上面产生的Provider<Gear>对象,MembersInjector<Bus>类型对象包含上面产生的Provider<Engine>类型对象
接下来调用的是DaggerBusComponent的inject()方法,其实调用的是Bus_MembersInjector的injectMembers()方法
@Override
public void injectMembers(Bus instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.engine = engineProvider.get();
}
该方法中,直接把engineProvider.get()返回的engine对象赋值给bus对象,完成注入,那engineProvider.get()调用的是什么呢,我们接着往下看,engineProvider.get()其实调用的是BusModule_ProvideEngineFactory类中的get方法
@Override
public Engine get() {
return Preconditions.checkNotNull(
module.provideEngine(gearProvider.get()),
"Cannot return null from a non-@Nullable @Provides method");
}
看到了吧,这就回到了Busmodule类了,调用
@Provides
Engine provideEngine(Gear gear){
return new Engine(gear);
}
同时关键的地方来了,我们关心的是这个参数gear就是由gearProvider.get()方法提供,这个方法调用BusModule_ProvideGearFactory类中的get()方法,
@Override
public Gear get() {
return Preconditions.checkNotNull(
module.provideGear(), "Cannot return null from a non-@Nullable @Provides method");
}
也是回到了我们写的BusModule类中,soga,至此我们分析完毕,谢谢大家的收看,我们下次再见。