Dagger2是Google在Square开源的Dagger的基础上将反射注入的方式修改到编译时而得到的依赖注入框架。
官方地址:GitHub
官方文档:https://google.github.io/dagger/
四个关键注解:
@Inject
用于类构造器和类的属性。
- 用在类的构造器上用来注解提供对象的方法,Dagger会根据该构造器来生成该类的工厂类
ClassName_Factory
。工厂类实现了Factory<T>
接口,通过覆写的get()
方法调用注解的构造方法提供类的对象:
public final class Noodle_Factory implements Factory<Noodle> {
private static final Noodle_Factory INSTANCE = new Noodle_Factory();
@Override
public Noodle get() {
return new Noodle();
}
public static Factory<Noodle> create() {
return INSTANCE;
}
/** Proxies {@link Noodle#Noodle()}. */
public static Noodle newNoodle() {
return new Noodle();
}
}
原始类:
class Noodle {
@Inject
public Noodle() {
}
@Override
public String toString() {
return "面条";
}
}
- 用在类的属性上用来注解该属性需要依赖注入。Dagger会为根据该类需要注入的属性生成
ClassName_MembersInjector
注入类,该类实现了MembersInjector<T>
接口。通过静态的create(arg...)
方法来生成实例,该方法的参数类型为需要注入的属性对应的Provider<T>
类型(Factory<T>
是Provider<T>
的子类型),参数个数与需要注入的字段个数一致。注入类通过覆写的injectMembers(T instance)
方法来注入目标类需要的属性:
public final class ZhaiNan_MembersInjector implements MembersInjector<ZhaiNan> {
private final Provider<Baozi> baoziProvider;
private final Provider<Noodle> noodleProvider;
public ZhaiNan_MembersInjector(Provider<Baozi> baoziProvider, Provider<Noodle> noodleProvider) {
assert baoziProvider != null;
this.baoziProvider = baoziProvider;
assert noodleProvider != null;
this.noodleProvider = noodleProvider;
}
public static MembersInjector<ZhaiNan> create(
Provider<Baozi> baoziProvider, Provider<Noodle> noodleProvider) {
return new ZhaiNan_MembersInjector(baoziProvider, noodleProvider);
}
@Override
public void injectMembers(ZhaiNan instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.baozi = baoziProvider.get();
instance.noodle = noodleProvider.get();
}
public static void injectBaozi(ZhaiNan instance, Provider<Baozi> baoziProvider) {
instance.baozi = baoziProvider.get();
}
public static void injectNoodle(ZhaiNan instance, Provider<Noodle> noodleProvider) {
instance.noodle = noodleProvider.get();
}
}
若一个类自身需要为别的类提供依赖(他的构造器用@Inject注解),同时也需要别的类提供依赖(他的属性用@Inject注解),他对应的工厂类会依赖于他对应的MembersInjector
,并调用MembersInjectors.injectMembers()
来为自身注入依赖:
public final class ZhaiNan_Factory implements Factory<ZhaiNan> {
private final MembersInjector<ZhaiNan> zhaiNanMembersInjector;
public ZhaiNan_Factory(MembersInjector<ZhaiNan> zhaiNanMembersInjector) {
assert zhaiNanMembersInjector != null;
this.zhaiNanMembersInjector = zhaiNanMembersInjector;
}
@Override
public ZhaiNan get() {
return MembersInjectors.injectMembers(zhaiNanMembersInjector, new ZhaiNan());
}
public static Factory<ZhaiNan> create(MembersInjector<ZhaiNan> zhaiNanMembersInjector) {
return new ZhaiNan_Factory(zhaiNanMembersInjector);
}
}
原始类:
public class ZhaiNan {
@Inject
Baozi baozi;
@Inject
Noodle noodle;
@Inject
public ZhaiNan() {
}
public String eat() {
StringBuilder sb = new StringBuilder();
sb.append("我吃的是 ");
if (baozi != null) {
sb.append(baozi.toString());
}
if (noodle != null) {
sb.append(" ");
sb.append(noodle.toString());
}
return sb.toString();
}
}
class Noodle {
@Inject
public Noodle() {
}
@Override
public String toString() {
return "面条";
}
}
@Module 和 @Provides
上面介绍了Dagger生成的核心类,即为被注入的属性生成的工厂类以及注入类,工厂类用来提供该属性需要的对象,注入类提供将该对象绑定要属性需要的方法。生成工厂类需要使用@Inject
注解提供依赖的类的构造函数,但现实情况是,我们很多时候没法修改该类,这个时候我们就需要手动实现提供该该类的对象的方法。使用@Module
和 @Provides
来解决这个问题。@Module
用来注解我们自己实现的工厂类,@Provides
用来注解里面的工厂方法,Dagger会为每一个工厂方法生成一个工厂类。假如@Module
标注的类名为ZhaiNanModule
,@Provides
标注的方法名为provideBaozi()
,生成的工厂类则为:
public final class ZhaiNanModule_ProvideBaoziFactory implements Factory<Baozi> {
private final ZhaiNanModule module;
public ZhaiNanModule_ProvideBaoziFactory(ZhaiNanModule module) {
assert module != null;
this.module = module;
}
@Override
public Baozi get() {
return Preconditions.checkNotNull(
module.provideBaozi(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<Baozi> create(ZhaiNanModule module) {
return new ZhaiNanModule_ProvideBaoziFactory(module);
}
}
Module 类:
@Module
public class ZhaiNanModule {
@Provides
public ZhaiNan provideZaiNan() {
return new ZhaiNan();
}
@Provides
public Noodle provideNoodle() {
return new Noodle();
}
@Provides
public Baozi provideBaozi() {
return new Baozi();
}
}
注意:
- 在
@Provides
标注的方法中直接new 出来的对象,即使该对象内部有需要被注入的属性,Dagger也没法自动去完成依赖注入。即Dagger不会为new出来的对象自动注入依赖。- 若提供依赖的类的构造方法使用了
@Inject
注解,并且@Module
注解的类也中提供了返回该类的方法,Dagger会优先使用@Module
注解的类中的方法。
@Component()
依赖提供方和依赖需求方的纽带。@Component()
注解的接口或抽象类中定义提供已经注入好依赖的对象的方法(前提是Module中或Dagger生成的代码中提供该对象的方法会注入该对象的依赖)或者为对象注入依赖方法。被它注解的接口中定义的方法若为返回一个对象,则该方法执行完后返回对象中定义的所有需要被注入的依赖都会被注入好,若该方法接受一个对象作为参数,则该方法执行完后该对象内需要被注入的属性都会被注入好。
若接口名称为ZhaiNanComponent
,则Dagger生成的类名为DaggerZhaiNanComponent
,并且实现了接口中定义的方法:
原始类:
@Component(modules = {ZhaiNanModule.class}) // 指定提供依赖方法的模块
public interface ZhaiNanComponent {
ZhaiNan get();
void inject(MainActivity mainActivity);
void inject(ZhaiNan zhaiNan);
}
生成的类:
public final class DaggerZhaiNanComponent implements ZhaiNanComponent {
private Provider<ZhaiNan> provideZaiNanProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private Provider<Baozi> provideBaoziProvider;
private Provider<Noodle> provideNoodleProvider;
private MembersInjector<ZhaiNan> zhaiNanMembersInjector;
private DaggerZhaiNanComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static ZhaiNanComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideZaiNanProvider = ZhaiNanModule_ProvideZaiNanFactory.create(builder.zhaiNanModule);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(provideZaiNanProvider);
this.provideBaoziProvider = ZhaiNanModule_ProvideBaoziFactory.create(builder.zhaiNanModule);
this.provideNoodleProvider = ZhaiNanModule_ProvideNoodleFactory.create(builder.zhaiNanModule);
this.zhaiNanMembersInjector =
ZhaiNan_MembersInjector.create(provideBaoziProvider, provideNoodleProvider);
}
@Override
public ZhaiNan get() {
return provideZaiNanProvider.get();
}
@Override
public void inject(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity);
}
@Override
public void inject(ZhaiNan zhaiNan) {
zhaiNanMembersInjector.injectMembers(zhaiNan);
}
public static final class Builder {
private ZhaiNanModule zhaiNanModule;
private Builder() {}
public ZhaiNanComponent build() {
if (zhaiNanModule == null) {
this.zhaiNanModule = new ZhaiNanModule();
}
return new DaggerZhaiNanComponent(this);
}
public Builder zhaiNanModule(ZhaiNanModule zhaiNanModule) {
this.zhaiNanModule = Preconditions.checkNotNull(zhaiNanModule);
return this;
}
}
}
现在我们可以这么使用该类:
@Inject
ZhaiNan zhaiNan;
// 为对象注入依赖
ZhaiNanComponent zhaiNanComponent = DaggerZhaiNanComponent.builder()
.zhaiNanModule(new ZhaiNanModule())
.build();
zhaiNanComponent.inject(this); // 执行后zhaiNan就会被赋值
zhaiNanComponent.inject(zhaiNan); // 要执行这一步,因为zhaiNan在Module里是new出来的
// 获取一个依赖被注入完毕的对象
zhaiNan = DaggerZhaiNanComponent.builder().build().get();
注意:若Module中提供依赖的方法为static,则可以用
ZhaiNanComponent zhaiNanComponent = DaggerZhaiNanComponent.create();
来创建Component
辅助性注解
@Singleton 和 @Scope
@Singleton
是@Scope
被注解的一个注解,用来和@Provides
注解一起注解提供依赖的方法,被@Singleton
注解的方法能在@Component
范围内提供单例(该Component同时也需要被@Singleton
注解)。我们可以直接使用@Singleton
,也可以像这样自定义一个局部单例注解:
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ActivityScoped {
}
其中@Scope
是必须的,其他可选。现在我们可以使用@ActivityScoped
去注解@Provides
方法和@Component
类,来指定在该@Component
中@Provides
方法返回同一个对象实例。使用@ActivityScoped
注解上面的provideBaozi()
方法后,生成的DaggerZhaiNanComponent
类的private void initialize(final Builder builder)
方法中生成provideBaoziProvider
方式变成了:
// 原来是
//this.provideBaoziProvider = ZhaiNanModule_ProvideBaoziFactory.create();
this.provideBaoziProvider = DoubleCheck.provider(ZhaiNanModule_ProvideBaoziFactory.create());
使用了DoubleCheck<T>
类来生成了一个代理,通过DoubleCheck
类覆写的get()
方法来提供单例,所以它能实现Component级别的单例。
@Named 和 @Qualifiers
当你需要在Module中定义多个返回同类型的方法的时候,@name
就派上用场了。@name
是@Qualifiers
注解的一个注解,用来注解@Provides
注解的提供依赖对象的方法,和@Inject
注解的需要被注入的对象,以区分使用哪个方法来提供实例:
@Module
public class ZhaiNanModule {
@Provides
@Named("baozi1")
public static Baozi provideBaozi1() {
return new Baozi();
}
@Provides
@Named("baozi2")
public static Baozi provideBaozi2() {
return new Baozi();
}
}
public class MainActivity extends AppCompatActivity {
@Inject
ZhaiNan zhaiNan;
@Inject
@Named("baozi1")
Baozi baozi;
@Inject
@Named("baozi2")
Baozi baozi2;
}
生成的DaggerZhaiNanComponent
类的private void initialize(final Builder builder)
方法中生成mainActivityMembersInjector
方式变成了:
this.mainActivityMembersInjector =
MainActivity_MembersInjector.create(
ZhaiNanModule_ProvideZaiNanFactory.create(),
ZhaiNanModule_ProvideBaozi1Factory.create(),
ZhaiNanModule_ProvideBaozi2Factory.create());
若不想写每次写个name,可以自定义一个注解:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Baozi1 {
}
延迟加载和强制重新加载
分别使用Lazy<T>
和Provider<T>
类来实现:
public class Test {
@Inject
@Named("Test")
Lazy<String> name;
@Inject
Provider<Integer> randomValue;
public String getName() {
return name.get();
}
public int getRandomValue() {
return randomValue.get().intValue();
}
}
这样当第一次调用getName()
时,我们需要的String
对象才被创建;而每次调用getRandomValue()
时,一个新的Integer对象都会被创建。
Component依赖
若一个Component需要依赖另一个,可以通过指定@Component(modules = XModule.class, dependencies = OtherComponent.class)
,这样就可以使用OtherComponent定义的方法。在创建Component的时候把依赖的Component传入:
XiaoChiComponent xiaoChiComponent = DaggerXiaoChiComponent.builder()
.build();
DaggerFoodComponent.builder()
.xiaoChiComponent(xiaoChiComponent)
.build()
.inject(this);
SubComponent
Component依赖类似于组合,而SubComponent类似于继承:
@Subcomponent(modules = FoodModule.class)
public interface SubComponent {
void inject(ThirdActivity activity);
}
@Component(modules = XiaoChiModule.class)
public interface ParentComponent {
SubComponent provideSubComponent();
}
DaggerParentComponent.builder().build()
.provideSubComponent().inject(this);