目录

  • 目录
  • 依赖注入
  • 依赖注入实现的三种方式
    • 1. 构造注入
    • 2. 属性注入
    • 3. 接口注入
  • Dagger2
  • Dagger2的引入
  • 不带Module的Inject方式(Inject+Component)
  • 带Module的Inject方式(Inject+Component+Module)
  • Module带参数
  • Scope作用域
  • Qualifier方法
  • Component间依赖的两种方式
    • a)Dependence方式
    • b)SubComponent方式
    • 两种方式的比较
  • 懒加载与重加载
  • 总结
  • 参考资料

依赖注入

依赖注入(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;@Overridepublic 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 {@Injectpublic 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";@InjectPerson person;@Overrideprotected 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());}@Overridepublic 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);}@Overridepublic 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();@Overridepublic 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 {@Providespublic 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;}@Overridepublic 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);}@Overridepublic 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;}@Providespublic Person providePerson(){return new Person(age);}@Providespublic 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;}@Providespublic int provideAge(){return age;}@Providespublic Person providePerson(){return new Person(age);}@Providespublic 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;}@ProvidesContext providersContext(){return  context;}@ProvidesDecorate 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 {@InjectDecorate decorate;@Overrideprotected 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);}@Overridepublic 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.*/@Deprecatedpublic 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_providersDecorateimplements Provider<Decorate> {private final AppComponent appComponent;com_skyblue_dragger2_AppComponent_providersDecorate(AppComponent appComponent) {this.appComponent = appComponent;}@Overridepublic 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 {@InjectDecorate decorate;@Overrideprotected 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);}@Overridepublic 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);}@Overridepublic 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 {@InjectLazy<Decorate> decorateLazy;@Overrideprotected 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);}@Overridepublic 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@Overridepublic 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/

深入浅出依赖注入框架Dagger2相关推荐

  1. 依赖注入框架Dagger2详解(一),依赖注入和控制反转的深入理解

    IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合.更优良的程序,而Dagger2框架是依赖注入思想践行者的优秀代表. 依赖注入框架Dagger2详解(一), ...

  2. Android 依赖注入框架 Dagger2使用

    前言 Dagger 2这个匕首确实很难上手,上手后又比较难瞬间掌握,可以这么说,刚开始使用就是用来尝(zhuang)鲜(X)的,但相信随着使用的加深,会不断体会到它对于整个项目架构的极强辅助作用,能使 ...

  3. Android:dagger2让你爱不释手-基础依赖注入框架篇

    前言 dagger2的大名我想大家都已经很熟了,它是解决Android或java中依赖注入的一个类库(DI类库).当我看到一些开源的项目在使用dagger2时,我也有种匆匆欲动的感觉,因此就立马想一探 ...

  4. Kotlin替换Dagger2/Hilt的依赖注入框架--Koin。

    Koin.Dagger2.Hilt 目前都是非常流行的库,面对这么多层出不穷的新技术,我们该做如何选择,是一直困扰我们的一个问题. Hilt 与 Dagger2 区别并不大,Hilt就是对Dagger ...

  5. Android神匕首—Dagger2依赖注入框架详解

    简介 Dagger-匕首,鼎鼎大名的Square公司旗下又一把利刃(没错!还有一把黄油刀,唤作ButterKnife) Dagger2 是一个Android依赖注入框架,由谷歌开发,最早的版本Dagg ...

  6. android dagger2 懒加载,Android Dagger依赖注入框架浅析

    今天接触了Dagger这套android的依赖注入框架(DI框架),感觉跟Spring 的IOC差不多吧.这个框架它的好处是它没有采用反射技术(Spring是用反射的),而是用预编译技术,因为基于反射 ...

  7. ASP.NET Core技术研究-探秘依赖注入框架

    ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务.提供服务.依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者. 毫不夸张的说,ASP.NET ...

  8. Android 依赖注入 DI - Dagger2

    1.依赖注入 (Dependency Injection) 1.1 面向接口编程 public interface Drivable {void drive(); }public class Bike ...

  9. android组件浮动在activity上_Jetpack Hilt 依赖注入框架上手指南

    code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:LvKang-insist 链接:https://juejin.im/post/5efdff9d6fb9a07e ...

最新文章

  1. C++ OJ 中多行数据输入(大小写转换、通过移位运算实现2的n次方、多组输入,每行输入数量不一样)
  2. 掌握ADO.NET的十个热门技巧
  3. Flume原理及使用案例
  4. php redis sorted set,Redis 有序集合(sorted set)
  5. 功能强大且易用的云打印解决方案
  6. 2021 常用的 7 款 MySQL 客户端工具
  7. graphpad做单因素方差分析_手把手教你用Graphpad做单因素方差分析
  8. 实现Android手机之间在局域网下传输任意文件
  9. 【记录】gis空间分析poi点分布的影响因素操作过程
  10. asp毕业设计—— 基于asp+access的论坛网站设计与实现(毕业论文+程序源码)——论坛网站
  11. Mybatisplus lambda写法随笔
  12. java 解析 svg文件_java – 如何加载和解析SVG文档
  13. 护眼台灯真的护眼吗?为家长推荐四款真正护眼的台灯
  14. Python实战|用可视化方式看新闻,迅速了解最新时事热点
  15. origin软件干嘛用的
  16. DIB-R 可微分渲染器使用
  17. 2045年千亿设备将互联 物联网安全需全球共治
  18. 深入理解搜索引擎——搜索评价指标
  19. torch学习 (三十七):DCGAN详解
  20. 【Java语言】项目实践:人机猜拳游戏(源码)(面向对象方法)

热门文章

  1. 阅读mutate源码学习dplyr
  2. Educational Codeforces Round 12 A. Buses Between Cities 水题
  3. CentOS 6.2下log4cplus的使用
  4. Myeclipse中遇到Unauthorized
  5. 自定义类似于listView中Item背景
  6. [转]pthread用于进程间通信
  7. 再谈 Struts1.x 的运行机制
  8. win10前面板耳机没声音
  9. [转] 字符集、字符编码
  10. DropDownList控件的AutoPostBack属性的问题 选择后,值也跟着刷新