dagger2是一个依赖注入框架,通过编译时生成代码来确保简单,可追溯,以及高性能。
依赖注入的好处:
- 依赖的注入和配置独立于组件之外。
- 因为对象是在一个独立、不耦合的地方初始化,所以当注入抽象方法的时候,我们只需要修改对象的实现方法,而不用大改代码库。
- 依赖可以注入到一个组件中:我们可以注入这些依赖的模拟实现,这样使得测试更加简单。
基本使用
几个基本的注解:
@Inject——用在构造函数,或者需要注入的对变量上。
如果使用在构造函数上,dagger会在需要构造实例时,获取必要的参数,并调用该构造方法。
如果使用在变量上,dagger会生成对应的实例。
public class BMW implements ICar {
IWheel wheel;
@Inject
public BMW(IWheel wheel) {
}
//或者构造函数和变量都加@Inject
/**
@Inject
public BMW(){
super();
}
@Inject
IWheel wheel;
*/
}
@Inject有些场景无效:
- 接口不能被构造;
- 第三方类库中的类不能使用@Inject;
- 可配置的对象需要配置。
@Module—
Module类中的方法专门提供依赖,当Dagger在构造类的实例时,从Module中获取需要的依赖。Module类可以设计分组,按照一定的规则,形成多个Module。
@Module
public class WheelModel {
@Provides
public static IWheel provideWheel...
}
@Provide
在Module类中的方法使用Provide注解,以此来告诉Dagger我们想要构造对象并提供更依赖。
可以直接生成一个对象实例:
@Module
public class WheelModel {
@Provides
public static IWheel provideWheel() {
return new BMWWheel();
}
}
provide方法也可以依赖其他对象,只需那个对象的构造方法有@Inject注解:
@Module
public class WheelModel {
@Provides
public static IWheel provideBMWWheel(BMWWheel wheel) {
return wheel;
}
}
对应的BMWWheel:
public class BMWWheel implements IWheel {
@Inject
public BMWWheel() {
super();
}
@Override
public int size() {
return 100;
}
@Override
public int color() {
return 10;
}
}
所以就是BMW依赖IWheel,由WheelModel的provideBMWWheel()方法提供,而provideBMWWheel()依赖BMWWheel,而BMWWheel的构造函数有@Inject,所以Dagger生成了一个BMWWheel对象实例,注入了BMW中。
@Binds
当需要注入的是接口的实例,那么可以使用@Binds来提供依赖,方法需要声明成abstract,Module类需要编程interface或者abstract
@Module
public interface WheelModel {
//或者 public abstract class WheelModel {
@Binds
abstract IWheel bindBMWWheel(BMWWheel wheel);
}
@Component——@Inject和@Module的桥梁,用@Component注解一个接口,并列出所需的@Modules组件,然后生成具体的实现代码。
@Component(modules = WheelModel.class)
public interface CarComponent {
BMW makeBmw();
}
项目build之后,dagger2会生成各种代码,具体的调用:
ICar bmw = DaggerCarComponent.create().makeBmw();
其中的create()方法其实是调用了DaggerCarComponent的Builder构建器的build()方法。
如果@Module的类有默认的构造方法(类,非接口),那么build()时,可以传入Module实例,如果没有默认构造函数,那么就会默认生成一个。那么调用DaggerCarComponent生成对象时,可以注入一个WheelModel实例:
DaggerCarComponent.builder().wheelModel(new WheelModel()).build().makeBmw().desc();
Dagger2给wheelModel()增加了deprecated注解,其实是因为此时WheelModule中的provideXX方法是静态的,不依赖WheelModel实例,所以无需传入实例。
如果@Componet注解的类是一个内部类,那么Dagger生成的类会包含嵌套的类名:
public class Boo {
static class Foo {
@Component(modules = WheelModel.class)
interface CarComponent {
BMW make();
}
}
}
那么生成的Componet类名为DaggerBoo_Foo_CarComponent