目录
依赖注入
依赖注入(DI)是控制反转(Inversion of Control,IoC)的一种重要方式,IoC是将依赖对象的创建和绑定通过被依赖对象类的外部来实现。依赖注入提供一种机制,将需要依赖对象的引用传递给被依赖对象。它是面向对象的一种设计模式,其目的是为了降低耦合。举个栗子:
public class Person {
Decorate decorate;
public Person(){
decorate = new Decorate(jacket,shoe);
}
}
这里的Person对象的初始化为实例化Decorate,如果Decorate类实例化参数增加,则必须对Person对象初始化进行修改。如果还有其他类的也是按照这种方式创建Decorate类,那么就需要修改多处,这违背了单一职责原则和开闭原则。因此需要引入依赖注入来解决这个问题。
依赖注入实现的三种方式
下面将会介绍三种简单的依赖注入方式,一般依赖注入的框架的基本原理基本一样,避免在被依赖对象中直接实例化依赖对象,而是通过其他方式引入。根据依赖注入的定义,下面例子中依赖对象为Decorate,被依赖对象为Person。
1. 构造注入
通过构造函数直接注入
public class Person {
private Decorate decorate;
public Person(Decorate decorate){
this.decorate = decorate;
}
}
2. 属性注入
通过属性来传递依赖即通过set方法
public class Person {
private Decorate decorate;
public void setPerson(Decorate decorate){
this.decorate = decorate;
}
}
3. 接口注入
相比前面两种方法,接口注入的方式显得有些复杂。需要先定义一个接口,包含一个设置依赖对象的方法,然后让被依赖对象继承并实现这个接口。
public interface Inject{
void inject(Decorate decorate)
}
public class Person implements Inject{
private Decorate decorate;
@Override
public void inject(Decorate decorate) {
this.decorate = decorate;
}
}
Dagger2
在github上Dagger2是这样定义的,Dagger2是一个Android和java快速依赖注入框架。Dragger2是在编译时注解的方式实现依赖注入,是Dagger的升级版,取消了反射的使用。通过@Component的接口替代ObjectGraph/Injector,从而使代码更精简。早期的一些注入框架是通过反射机制在运行时完成注入的工作,而反射对性能影响很大,所以现在基本上是采用编译时通过工具生成相应的类文件实现的。
Dagger2的引入
完成Dagger2的依赖方式有两种,分别为annotationProcessor和android-apt。android-apt是开发者自己开发的apt框架,随着谷歌Android Gradle2.2插件的发布,插件提供了annotationProcessor来替换android-apt,自此基本上都使用annotationProcessor。
项目中通过annotationProcessor的方式进行依赖,在app的build.gradle添加:
implementation 'com.google.dagger:dagger:2.10'
annotationProcessor "com.google.dagger:dagger-compiler:2.10"
implementation "org.glassfish:javax.annotation:10.0-b28"
不带Module的Inject方式(Inject+Component)
1.定义一个Person类,在构造函数前加上@Inject,表明支持依赖注入
public class Person {
@Inject
public Person(){
}
public String getSex(){
return "male";
}
}
2.定义接口MainActivityComponent,在接口前添加@Component,定义相应的抽象方法,方法的参数为需要注入对象的真实所在的类,方法名一般为Inject。Component可以理解为Person(依赖对象)和MainActivity(被依赖对象)之间的桥梁
@Component
public interface MainActivityComponent {
void inject(MainActivity activity);
}
3.对项目进行Rebuild,Dagger2框架会根据MainActivityComponent自动生成DaggerMainActivityComponent(命名规则Dagger+Component名称)。在MainActivity声明Person对象,并用@Inject的注解,然后通过DaggerMainActivityComponent注入Person对象。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Inject
Person person;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.builder().build().inject(this);
Log.d(TAG,person.getSex());
}
}
11:32:53.851 29222-29222/com.skyblue.dragger2 D/MainActivity: male
可以看出MainActivity成功注入了Person类,下面分析是如何注入Person类的:
打开DaggerMainActivityComponent,可以看出其对应的路径\app\build\generated\source\apt\debug,在其目录下同时也有其他两个类Person_Factory,MainActivity_MembersInjector。
在MainActivity中DaggerMainActivityComponent.builder().build().inject(this)将会实例化DaggerMainActivityComponent,在实例化的过程中调用了initialize函数,而该函数的作用是调用了MainActivity_MembersInjector的create函数。再看类中的Inject函数,该类继承了MainActivityComponent。可以猜测mainActivityMembersInjector.injectMembers(activity)完成了Person类的注入。
package com.skyblue.dragger2;
import dagger.MembersInjector;
import javax.annotation.Generated;
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerMainActivityComponent implements MainActivityComponent {
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainActivityComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static MainActivityComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create());
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private Builder() {}
public MainActivityComponent build() {
return new DaggerMainActivityComponent(this);
}
}
}
MainActivity_MembersInjector类是实例化Person类的关键,也是注入具体的实现方式。在上面讨论调用到该类的create的函数,create函数传入的参数为Person_Factory.create,inject调用了mainActivityMembersInjector.injectMembers(activity)即调用了instance.person = personProvider.get();
package com.skyblue.dragger2;
import dagger.MembersInjector;
import javax.annotation.Generated;
import javax.inject.Provider;
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<Person> personProvider;
public MainActivity_MembersInjector(Provider<Person> personProvider) {
assert personProvider != null;
this.personProvider = personProvider;
}
public static MembersInjector<MainActivity> create(Provider<Person> personProvider) {
return new MainActivity_MembersInjector(personProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.person = personProvider.get();
}
public static void injectPerson(MainActivity instance, Provider<Person> personProvider) {
instance.person = personProvider.get();
}
}
Person_Factory是对应Person类中在构造函数前添加@Inject注解,由Dragger2自动生成的对用的工厂类,用于实例化对象,来提供给需要的类。Person_Factory.create()的函数实例化了Factory,mainActivityMembersInjector.injectMembers(activity)调用的instance.person = personProvider.get()从而具体实例化了Person类。
package com.skyblue.dragger2;
import dagger.internal.Factory;
import javax.annotation.Generated;
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class Person_Factory implements Factory<Person> {
private static final Person_Factory INSTANCE = new Person_Factory();
@Override
public Person get() {
return new Person();
}
public static Factory<Person> create() {
return INSTANCE;
}
}
MainActivity_MembersInjector的create函数传入的对象类型为Provider,而Person_Factory.create()的类型为Factory,那么它们之前一定是一种继承的关系。通过查看Factory继承了Provider。
package dagger.internal;
import dagger.Provides;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Scope;
/**
* An {@linkplain Scope unscoped} {@link Provider}. While a {@link Provider} <i>may</i> apply
* scoping semantics while providing an instance, a factory implementation is guaranteed to exercise
* the binding logic ({@link Inject} constructors, {@link Provides} methods) upon each call to
* {@link #get}.
*
* <p>Note that while subsequent calls to {@link #get} will create new instances for bindings such
* as those created by {@link Inject} constructors, a new instance is not guaranteed by all
* bindings. For example, {@link Provides} methods may be implemented in ways that return the same
* instance for each call.
*
* @author Gregory Kick
* @since 2.0
*/
public interface Factory<T> extends Provider<T> {
}
通过上面的分析基本清楚了,Person是如何在MainActivity注入的。总结一下:
首先在定义了Person类中注解@Inject由Dagger2生成了其对应的工厂类Factory,再定义注入的Component接口,声明注入的方法,Dagger2自动生成了DaggerMainActivityComponent,并在其类中调用了MainActivity_MembersInjector的inject方法,该方法封装了通过Factory 的get方法实现了对Person的实例化注入。
带Module的Inject方式(Inject+Component+Module)
在上面的Person中是自己定义的类,如果是某个库中的类,则是不能够去该类中添加@Inject注解了,那么注入这种类该如何注入呢,这个时候就需要Module。Module可以理解为对对象的实例化,向Component的提供依赖对象。下面以Person类为对象说明:
1.创建一个MainModule,并用@Module注解,在类中提供Person对象的方法并用@Provider注解(取消之前Person类中的@Inject注解)
@Module
public class MainModule {
@Provides
public Person providePerson(){
return new Person();
}
}
2.修改MainActivityComponent,为其添加Module应用,来说明其可能需要用到MainModule中提供的对象。
@Component(modules = MainModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
3.MainActivity保持不变
16:11:20.927 7148-7148/com.skyblue.dragger2 D/MainActivity: male
可以看出和上面的例子结果一样,主要不同的是增加了MainModule。Dagger2自动生成的类中没有了Person_Factory,而是MainModule_ProvidePersonFactory类。可以看出该类和Person_Factory本质上是一样的,提供依赖对象。如果MainModule中还有其它的Providers那么会生成对应数量的MainModule_ProvideXXFactory类,其类中会提供对应数量的get方法。
package com.skyblue.dragger2;
import dagger.internal.Factory;
import dagger.internal.Preconditions;
import javax.annotation.Generated;
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class MainModule_ProvidePersonFactory implements Factory<Person> {
private final MainModule module;
public MainModule_ProvidePersonFactory(MainModule module) {
assert module != null;
this.module = module;
}
@Override
public Person get() {
return Preconditions.checkNotNull(
module.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<Person> create(MainModule module) {
return new MainModule_ProvidePersonFactory(module);
}
}
DaggerMainActivityComponent基本上保持不变。
package com.skyblue.dragger2;
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 DaggerMainActivityComponent implements MainActivityComponent {
private Provider<Person> providePersonProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainActivityComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static MainActivityComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.providePersonProvider = MainModule_ProvidePersonFactory.create(builder.mainModule);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(providePersonProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private MainModule mainModule;
private Builder() {}
public MainActivityComponent build() {
if (mainModule == null) {
this.mainModule = new MainModule();
}
return new DaggerMainActivityComponent(this);
}
public Builder mainModule(MainModule mainModule) {
this.mainModule = Preconditions.checkNotNull(mainModule);
return this;
}
}
}
Module带参数
一般情况下大多数的类都需要传入参数的,下面看下带参数的类的实例化是如何的。
1. 修改Person类
public class Person {
private int age ;
public Person(int age){
this.age = age;
}
public String getSex(){
return "male";
}
public int getAge(){
return age;
}
2.将Person类的age参数传入
@Module
public class MainModule {
int age;
public MainModule(int age){
this.age = age;
}
@Provides
public Person providePerson(){
return new Person(age);
}
@Provides
public Decorate providerDecorate(){
return new Decorate();
}
}
3.在MainActivity中设置MainModule对象的参数
DaggerMainActivityComponent.builder().mainModule(new MainModule(19)).build().inject(this);
16:50:37.343 8787-8787/? D/MainActivity: 19
需要注意的是在无参数的时候,DaggerMainActivityComponent会提供create方法,但是有参数时,只有build方法,因为需要传入MainModule对象。一般建议通过provide方法提供参数,主要是解耦和增加代码的可读性。
@Module
public class MainModule {
int age;
public MainModule(int age){
this.age = age;
}
@Provides
public int provideAge(){
return age;
}
@Provides
public Person providePerson(){
return new Person(age);
}
@Provides
public Decorate providerDecorate(){
return new Decorate();
}
}
Module中不能出现参数和返回参数一致的情况,否则会导致死循环。如:
@Provides
public int provideAge(int age){
return age;
}
Scope作用域
通过Singleton注解的例子来了解作用域,在MainActivity中注入两个Person对象
@Inject
Person person1;
@Inject
Person person2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.builder().mainModule(new MainModule(19)).build().inject(this);
Log.d(TAG,person1+"");
Log.d(TAG,person2+"");
}
17:09:29.532 9503-9503/? D/MainActivity: com.skyblue.dragger2.Person@29c76f
com.skyblue.dragger2.Person@b67ec7c
可以看到有两个不同的对象,那么怎么才能够让他们保持单例呢?这时就需要Singleton注解,那么注解放在什么地方呢?主要要放在两个地方。
1.提供Person对象的地方
需要注意的是@Inject和@Singleton不能同时使用,所以只能放在Module中。
@Singleton
@Provides
public Person providePerson(){
return new Person(age);
}
2.依赖对象和被依赖对象的桥梁component
@Singleton
@Component(modules = MainModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
17:17:40.525 10490-10490/com.skyblue.dragger2 D/MainActivity: com.skyblue.dragger2.Person@29c76f
com.skyblue.dragger2.Person@29c76f
添加Singleton注解前后主要的不同是在providePersonProvider获取的不同,添加后添加了DoubleCheck.provider检查。
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.providePersonProvider =
DoubleCheck.provider(MainModule_ProvidePersonFactory.create(builder.mainModule));
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(providePersonProvider);
}
/** Returns a {@link Provider} that caches the value from the given delegate provider. */
public static <T> Provider<T> provider(Provider<T> delegate) {
checkNotNull(delegate);
if (delegate instanceof DoubleCheck) {
/* This should be a rare case, but if we have a scoped @Binds that delegates to a scoped
* binding, we shouldn't cache the value again. */
return delegate;
}
return new DoubleCheck<T>(delegate);
}
如果添加了scope类型的注解后,将会返回之前的缓存对象。
Singleton的注解定义为:
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
将上面的Singleton换成SingletonTest,引用@SingletonTest注释,效果一样。还要一点需要注意的是Scope取决于Component的周期长短,如果在应用的Application中注入,那么周期是整个应用程序,如果只是MainActivity那么周期只是Activity的周期。如果在两个Component的中注入了同一个对象,那么这两个对象即使设定了Scope,并不是同一个对象,因为Component的之间是相互独立的。
Qualifier方法
当Module中有两个返回值相同的方法时,可以使用@Name区分,
@Named("two")
@Provides
String providesString1() {
return "test1";
}
@Named("three")
@Provides
String providesString2() {
return "test2";
}
// MainActivity
@Named("two")
@Inject String test1;
@Named("three")
@Inject String test2;
Qualifier和Scope一样,因此我们也可以自定义注解替代@Name
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {
/** The name. */
String value() default "";
}
Component间依赖的两种方式
当某个依赖对象在多个Component都需要时,没有必要在每个Component的中注入依赖。Component间的依赖有两种方式dependence和subcomponent,有些像组合和继承的关系。
a)Dependence方式
1.定义一个类对象
public class Decorate {
public Decorate(){
}
}
2.定义一个全局的Component
@Component(modules = AppModule.class)
public interface AppComponent {
Decorate providersDecorate();
}
3.定义Module提供对象
@Module
public class AppModule {
Context context;
public AppModule(Context context){
this.context = context;
}
@Provides
Context providersContext(){
return context;
}
@Provides
Decorate providersDecorate(){
return new Decorate();
}
}
4.在MainActivityComponent中添加其他Component的依赖
@Singleton
@Component(dependencies = AppComponent.class,modules = MainModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
5.在MainActivity中注入,通过AppComponent将对象提供给MainActivity
public class MainActivity extends AppCompatActivity {
@Inject
Decorate decorate;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppComponent appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
DaggerMainActivityComponent.builder().appComponent(appComponent).mainModule(new MainModule(10)).build().inject(this);
Log.d("dragger2",decorate+"");
}
}
07-09 19:10:11.604 23155-23155/? D/dragger2: com.skyblue.dragger2.Decorate@db9ce1a
再分析下生成的文件,这里主要看下DaggerMainActivityComponent,看如何获取到Decorate对象的
package com.skyblue.dragger2;
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 DaggerMainActivityComponent implements MainActivityComponent {
private Provider<Decorate> providersDecorateProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainActivityComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.providersDecorateProvider =
new com_skyblue_dragger2_AppComponent_providersDecorate(builder.appComponent);
this.mainActivityMembersInjector =
MainActivity_MembersInjector.create(providersDecorateProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private AppComponent appComponent;
private Builder() {}
public MainActivityComponent build() {
if (appComponent == null) {
throw new IllegalStateException(AppComponent.class.getCanonicalName() + " must be set");
}
return new DaggerMainActivityComponent(this);
}
/**
* @deprecated This module is declared, but an instance is not used in the component. This
* method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
*/
@Deprecated
public Builder mainModule(MainModule mainModule) {
Preconditions.checkNotNull(mainModule);
return this;
}
public Builder appComponent(AppComponent appComponent) {
this.appComponent = Preconditions.checkNotNull(appComponent);
return this;
}
}
private static class com_skyblue_dragger2_AppComponent_providersDecorate
implements Provider<Decorate> {
private final AppComponent appComponent;
com_skyblue_dragger2_AppComponent_providersDecorate(AppComponent appComponent) {
this.appComponent = appComponent;
}
@Override
public Decorate get() {
return Preconditions.checkNotNull(
appComponent.providersDecorate(),
"Cannot return null from a non-@Nullable component method");
}
}
}
在initialize中还是通过provider对象的方式来获取AppComponent依赖提供的对象。可以看到在获取providersDecorateProvider时,新建了一个内部静态类,命名方式为包名+依赖组件名+提供依赖对象的方法名,传入的参数为通过建造者模式获取的组件对象。而是的操作和前面的基本相同。通过生成的代码可以知道AppComponent只是相当于对象的转发,通过这种方式被其他的Component依赖。
b)SubComponent方式
1.修改Dependence方式中AppComponent,不再提供依赖对象,而是变成子Component,直接使用AppModule完成对象的注入。
@Component(modules = AppModule.class)
public interface AppComponent {
MainActivityComponent acitvityComponet();
}
2.修改Dependence方式中的MainActivityComponent
@Singleton
@Subcomponent (modules = MainModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
3.在MainActivity中添加依赖
public class MainActivity extends AppCompatActivity {
@Inject
Decorate decorate;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerAppComponent.builder().appModule(new AppModule(this)).build().acitvityComponet().inject(this);
Log.d("dragger2",decorate+"");
}
}
07-09 19:45:01.862 23864-23864/? D/dragger2: com.skyblue.dragger2.Decorate@db9ce1a
再看生成的代码,这里主要不同的是DaggerAppComponent
package com.skyblue.dragger2;
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 DaggerAppComponent implements AppComponent {
private Provider<Decorate> providersDecorateProvider;
private DaggerAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.providersDecorateProvider = AppModule_ProvidersDecorateFactory.create(builder.appModule);
}
@Override
public MainActivityComponent acitvityComponet() {
return new MainActivityComponentImpl();
}
public static final class Builder {
private AppModule appModule;
private Builder() {}
public AppComponent build() {
if (appModule == null) {
throw new IllegalStateException(AppModule.class.getCanonicalName() + " must be set");
}
return new DaggerAppComponent(this);
}
public Builder appModule(AppModule appModule) {
this.appModule = Preconditions.checkNotNull(appModule);
return this;
}
}
private final class MainActivityComponentImpl implements MainActivityComponent {
private MembersInjector<MainActivity> mainActivityMembersInjector;
private MainActivityComponentImpl() {
initialize();
}
@SuppressWarnings("unchecked")
private void initialize() {
this.mainActivityMembersInjector =
MainActivity_MembersInjector.create(DaggerAppComponent.this.providersDecorateProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
}
}
代码中DaggerAppComponent中为子Component生成了一个内部类,命名方式为子Componet名称+Impl,通过AppComponent提供的接口,来获取该内部对象。在initialize中通过providersDecorateProvider(AppModule生成)最后实现注入对象。
两种方式的比较
两种方式都可以实现Component之间的依赖对象关联,选择哪种方式进行关联,需要根据具体的情形。Dependencies像类中的组合关系,subcomponent像类中的继承关系。
两者在Scope时需要注意:
Dependencies中两个有依赖关系的Component不能有相同的@Scope注解而subcomponent则可以。
两种方式的比较
Dependencies
特点:
可以知道对应Component的所依赖的Component
每个Component都会生成对应的DaggerXxxComponent
被依赖的Component会为依赖Component提供对象的获取
使用依赖Component传入被依赖Component完成注入
注意
被依赖Component中没有显式的提供依赖无法完成注入
Subcomponent
特点
父Component可以管理子Component
只有父Component会生成DaggerXxxComponent
默认可以获取到父子两个Component使用到的Module所提供的对象
使用父Component并选择指定的子Component完成注入
懒加载与重加载
懒加载:通过调用get方法时才创建对象,以后获取的对象为同一对象
重加载:通过调用get方法时会强制重新创建对象,对象是否重建取决于Module的实现方式(@Scope注释)
public class MainActivity extends AppCompatActivity {
@Inject
Lazy<Decorate> decorateLazy;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerAppComponent.builder().appModule(new AppModule(this)).build().acitvityComponet().inject(this);
Decorate decorate = decorateLazy.get();
}
}
再看apt生成的代码,主要看注入部分的代码
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<Decorate> decorateLazyProvider;
public MainActivity_MembersInjector(Provider<Decorate> decorateLazyProvider) {
assert decorateLazyProvider != null;
this.decorateLazyProvider = decorateLazyProvider;
}
public static MembersInjector<MainActivity> create(Provider<Decorate> decorateLazyProvider) {
return new MainActivity_MembersInjector(decorateLazyProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.decorateLazy = DoubleCheck.lazy(decorateLazyProvider);
}
public static void injectDecorateLazy(
MainActivity instance, Provider<Decorate> decorateLazyProvider) {
instance.decorateLazy = DoubleCheck.lazy(decorateLazyProvider);
}
}
在该类中injectMembers方法使用了DoubleCheck.lazy处理后得到Lazy对象,而一般情况是通过provide的get方法获取到对象。下面是DoubleCheck.lazy的代码
/** Returns a {@link Lazy} that caches the value from the given provider. */
public static <T> Lazy<T> lazy(Provider<T> provider) {
if (provider instanceof Lazy) {
@SuppressWarnings("unchecked")
final Lazy<T> lazy = (Lazy<T>) provider;
// Avoids memoizing a value that is already memoized.
// NOTE: There is a pathological case where Provider<P> may implement Lazy<L>, but P and L
// are different types using covariant return on get(). Right now this is used with
// DoubleCheck<T> exclusively, which is implemented such that P and L are always
// the same, so it will be fine for that case.
return lazy;
}
return new DoubleCheck<T>(checkNotNull(provider));
}
/**
* A {@link Lazy} and {@link Provider} implementation that memoizes the value returned from a
* delegate using the double-check idiom described in Item 71 of <i>Effective Java 2</i>.
*/
public final class DoubleCheck<T> implements Provider<T>, Lazy<T> {
private static final Object UNINITIALIZED = new Object();
private volatile Provider<T> provider;
private volatile Object instance = UNINITIALIZED;
private DoubleCheck(Provider<T> provider) {
assert provider != null;
this.provider = provider;
}
@SuppressWarnings("unchecked") // cast only happens when result comes from the provider
@Override
public T get() {
Object result = instance;
if (result == UNINITIALIZED) {
synchronized (this) {
result = instance;
if (result == UNINITIALIZED) {
result = provider.get();
/* Get the current instance and test to see if the call to provider.get() has resulted
* in a recursive call. If it returns the same instance, we'll allow it, but if the
* instances differ, throw. */
Object currentInstance = instance;
if (currentInstance != UNINITIALIZED && currentInstance != result) {
throw new IllegalStateException("Scoped provider was invoked recursively returning "
+ "different results: " + currentInstance + " & " + result + ". This is likely "
+ "due to a circular dependency.");
}
instance = result;
/* Null out the reference to the provider. We are never going to need it again, so we
* can make it eligible for GC. */
provider = null;
}
}
}
return (T) result;
}
可以看出DoubleCheck.lazy实例化了一个DoubleCheck对象,再封装Provider通过双重检查机制来实现单例。
总结
Inject主要是标注需要注入的对象
Component主要是提供注入对象的入口
Module主要是在对象类中不能添加Inject的标注时,提供方法,对象,返回值
Scope主要是用于作用域的标注,通过Singleton或者自定义注解实现单例
Component间相互依赖的两种方式dependencies和subcomponent,类似组合和继承的关系
懒加载(Lazy)和重加载(Provider):懒加载是有Provider封装好的DoubleCheck对象
参考资料
https://github.com/google/dagger
https://www.jianshu.com/p/b266314a97db?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
http://alighters.com/blog/2016/04/15/dagger2-indepth-understanding/
https://google.github.io/dagger/api/2.0/index.html
http://www.cnblogs.com/liuhaorain/p/3747470.html
https://www.jianshu.com/p/22c397354997/