Dagger2是一个依赖注入框架,我们经常用到的依赖注入框架还有ButterKnife。说到这里,首先了解一个概念:控制反转。
控制反转(又叫IOC:Inversion Of Control):是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统的所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
说到Dagger2的使用,我们首先了解一下使用Dagger2有什么好处?
Dagger2是用来使代码解耦的,一个类的new代码是非常可能充斥在app的多个类中的,假如该类的构造函数发生变化,那这些涉及到的类都得进行修改。
1.如果使用Dagger2的Inject注解构造函数,即使构造函数发生较大的变化,我们基本上都不需要修改任何代码
2.Dagger2可以更好的帮助我们解耦 不用担心对象或者属性在被生命周期持有导致的未释放
Dagger 是通过@Inject使用具体的某个对象,这个对象呢,由@Provides注解提供,但是呢,@Provides只能在固定的模块中,也就是@Module注解,我们查找的时候,不是直接去找模块,而是去找@Component
可以这么理解 @Module 是提供你想要东西一个盒子,那么盒子是通过方法提供给你东西 但是Dagger他又不知那些方法可以提供,那么就需要在你的方法上标注一个这样的@Provides来告诉Dagger
基本使用
Dagger2,分为三部分:依赖提供方、依赖需求方、依赖注入容器(即二者之间的桥梁)。
在Dagger2中被@Module注解的类作为提供方、@Component注解的类作为桥梁、@Inject注解的变量作为需求方
@Inject注解有两个作用:
作为依赖提供方,@Inject注解添加到类的构造函数上
作为依赖需求方,@Inject注解添加到成员变量上
@Provides
用来标注Module类中的提供依赖对象的方法进行标注,该方法在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注了@Inject 的变量赋值。
@Singleton
默认情况下,@Inject
获取到的依赖对象是非单例的,要想实现单例,需要用@Singleton
对Module中的provide方法和Conponent接口进行标注。
使用过程
1.导包
// dagger2 implementation 'com.google.dagger:dagger:2.23.1' annotationProcessor 'com.google.dagger:dagger-compiler:2.23.1'
2.创建实体类并在实体类的构造方法上添加上@Inject注解,作为依赖的提供方
注意:只能有一个构造方法可以被加上@Inject注解,否则会报错
Types may only contain one @Inject constructor
public class Person { public String name; public int age; //依赖的提供方 @Inject public Person(String name, int age) { this.name = name; this.age = age; } }
3. 创建一个Module类
@Module public class MainActivityModule { @Provides public Person providePerson(){ return new Person("xiaowang",30); } }
这个类的命名以Module结尾,里面针对Person类含有@Inject构造函数的参数,添加provide方法,这些provide方法需要添加@Provides注解,并且方法命名以provide开头。Module类作为依赖提供方,提供构造函数中的参数。Module 其实是一个简单工厂模式,Module 里面的方法都是创建相应类实例的方法
4.创建Component类,作为依赖提供方和依赖需求方直接的桥梁:
@Component(modules = MainActivityModule.class) public interface MainActivityComponent { void inject(MainActivity mainActivity); }
@Component
一般用来注解接口,负责在@Inject
和@Module
之间建立连接。实例化@Inject
注解的类时,遇到没有构造函数的类依赖,则该依赖由@Module
修饰的类提供
5.在Activity中,声明一个类实例对象,并加上@Inject注解
@Inject Person mPerson; DaggerMainActivityComponent.builder() .mainActivityModule(new MainActivityModule()) .build() .inject(this);
获取单例对象
局部单例
在 Component类上添加@Singleton
在Module的provide方法上加上@Singleton
全局单例
在局部单例的基础上
创建Application,并在Application中创建Component
public class MyApplication extends Application { MainActivityComponent mComponent; @Override public void onCreate() { super.onCreate(); mComponent = DaggerMainActivityComponent.builder().mainActivityModule(new MainActivityModule()).build(); } public MainActivityComponent getComponent() { return mComponent; } }
使用时,使用Application注入
((MyApplication) getApplication()).getComponent().inject(this);
所有用注解标注的类,Dagger2都会用APT在build下去生成对应的辅助类,这些辅助类的名字是根据dagger-compiler注解依赖库中的命名规则生成的。
手动创建 | APT生成 | 命名规则 | 注解 |
MainActivity | MainActivity_MembersInjector | 类名_MembersInjector | @Inject |
TwoActivity | TwoActivity_MembersInjector | 类名_MembersInjector | @Inject |
MainActivityComponent | DaggerMainActivityComponent | Dagger对象名Component | @Component |
MainActivityModule | MainActivityModule_ProvidePersonFactory | 对象名Module_方法名Factory | @Module @Provides |
Person | Person_Factory | 对象名_Factory | @Inject |
public final class DaggerMainActivityComponent implements MainActivityComponent { private Provider<Person> providePersonProvider; private DaggerMainActivityComponent(MainActivityModule mainActivityModuleParam) { initialize(mainActivityModuleParam); } //使用构造者模式实例化DaggerMainActivityComponent对象 public static Builder builder() { return new Builder(); } public static MainActivityComponent create() { return new Builder().build(); } @SuppressWarnings("unchecked") private void initialize(final MainActivityModule mainActivityModuleParam) { this.providePersonProvider = DoubleCheck.provider(MainActivityModule_ProvidePersonFactory.create(mainActivityModuleParam)); } @Override public void inject(MainActivity mainActivity) { injectMainActivity(mainActivity);} @Override public void injectTwo(TwoActivity twoActivity) { injectTwoActivity(twoActivity);} //4 Activity中的@Inject生成injectMainActivity方法,通过MainActivityModule_ProvidePersonFactory来获取依赖注入对象 private MainActivity injectMainActivity(MainActivity instance) { MainActivity_MembersInjector.injectMPerson(instance, providePersonProvider.get()); MainActivity_MembersInjector.injectMPerson1(instance, providePersonProvider.get()); return instance; } private TwoActivity injectTwoActivity(TwoActivity instance) { TwoActivity_MembersInjector.injectMPerson(instance, providePersonProvider.get()); return instance; } public static final class Builder { private MainActivityModule mainActivityModule; private Builder() { } //2 传入MainActivityModule对象 public Builder mainActivityModule(MainActivityModule mainActivityModule) { this.mainActivityModule = Preconditions.checkNotNull(mainActivityModule); return this; } //3 实例化DaggerMainActivityComponent public MainActivityComponent build() { if (mainActivityModule == null) { this.mainActivityModule = new MainActivityModule(); } return new DaggerMainActivityComponent(mainActivityModule); } } }
public final class MainActivityModule_ProvidePersonFactory implements Factory<Person> { private final MainActivityModule module; public MainActivityModule_ProvidePersonFactory(MainActivityModule module) { this.module = module; } @Override public Person get() { return providePerson(module); } public static MainActivityModule_ProvidePersonFactory create(MainActivityModule module) { return new MainActivityModule_ProvidePersonFactory(module); } //5 通过MainActivityModule拿到Person对象,并用Dagger2提供的Preconditions.checkNotNull()方法来检查获取到的对象是否为空 public static Person providePerson(MainActivityModule instance) { return Preconditions.checkNotNull(instance.providePerson(), "Cannot return null from a non-@Nullable @Provides method"); } }
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> { private final Provider<Person> mPersonAndMPerson1Provider; public MainActivity_MembersInjector(Provider<Person> mPersonAndMPerson1Provider) { this.mPersonAndMPerson1Provider = mPersonAndMPerson1Provider; } public static MembersInjector<MainActivity> create(Provider<Person> mPersonAndMPerson1Provider) { return new MainActivity_MembersInjector(mPersonAndMPerson1Provider);} @Override public void injectMembers(MainActivity instance) { injectMPerson(instance, mPersonAndMPerson1Provider.get()); injectMPerson1(instance, mPersonAndMPerson1Provider.get()); } //6 将获取到的Person对象赋值给Activity中的mPerson public static void injectMPerson(MainActivity instance, Person mPerson) { instance.mPerson = mPerson; } public static void injectMPerson1(MainActivity instance, Person mPerson1) { instance.mPerson1 = mPerson1; } }