警告!这不是一个干货的文章!java
我的认为,学技术不宜太浮躁。对于一项技术一味地追求干货其实并不必定有用,货太干容易噎着,哈哈~不如按部就班慢下来,一点点去体会技术的来龙去脉。(这个系列适合于:了解但没有在项目里大规模应用Dagger2的读者)app
出来混早晚要还的,技术债Dagger2:Android篇(上)ide
出来混早晚要还的,技术债Dagger2:Android篇(中)@Scope、@Singletonpost
本觉得阅读一些文档,写一些Demo就能驾驭工做中的项目...我错了,我不再会有这么愚蠢的想法了... 这么多依赖关系,谁扛得住啊!因此仍是一点点来吧。学习
前俩篇文章事后,我猜你们对下面的代码已经很熟悉了:ui
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
SharedPreferences getSharedPrefs();
}
@Module
public class AppModule {
Application application;
public AppModule(Application application) {
this.application = application;
}
@Provides
Application providesApplication() {
return application;
}
@Provides
@Singleton
public SharedPreferences providePreferences() {
return application.getSharedPreferences(DATA_STORE,Context.MODE_PRIVATE);
}
}
DaggerAppComponent appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
复制代码
很基本,很简单的Dagger应用。不过你们有没有感受到这个appModule(new AppModule(this))
特别烦?安利我用的时候,说依赖注入,看不见new。我哼哧哼哧写这么多,这不仍是new出来的?this
那么问题来了,是否是能够不须要appModule(new AppModule(this))
呢?固然能够。用过Dagger-Android
的朋友,确定很清楚,的确看不到任何new。那么这篇文章,我们就来看看如何完全不用new。spa
固然这也是Dagger-Android的原理code
作这一切的前提是这个注解。这个注解是干啥的呢?说白了,给Component提供Module的依赖。
我们先来想一个问题,下面代码存在的意义:
DaggerAppComponent appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
复制代码
Dagger为咱们所需的依赖生成实例,那么必然须要构建整个依赖关系网。Dagger就算是再神奇,也不可能凭空把整个咱们所须要依赖关系构建出来,因此须要咱们适时的“提供和引导”。那么new AppModule(this)
就是给Dagger进行提供,由于从咱们上述的代码中,Dagger是不知道该怎么去实例化这个AppModule
,所以须要咱们对其进行提供。
那么话又说回来,咱们在上述的代码中,告诉它如何去实例化AppModule
,不就能够避免咱们手动去new AppModule(this)
了么?
没错,@Component.Builder
就是作这个的。
累死了,绕了一圈不知道你们理没理解@Component.Builder存在的含义了。
对于咱们的AppModule
来讲,实例化它的关键是如何提供一个Application
。
public AppModule(Application application) {
this.application = application;
}
复制代码
对于Dagger也是如此,它不能实例化AppModule
的缘由是它不知道或者说没办法去获取一个Application
实例。所以,对于Dagger来讲,咱们应该给它提供Application
的实例,而非AppModule
。
改造须要一步步来:第一步,咱们使用@Component.Builder
去改造AppComponent
:
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
SharedPreferences getSharedPrefs();
// 改造内容
@Component.Builder
interface Builder {
AppComponent build();
// 此时还未改造这行代码
Builder appModule(AppModule appModule);
}
}
复制代码
如今咱们告诉了Dagger,你要以
@Component.Builder
注解的接口那样去实例化咱们所需的AppComponent
。
是否是发现这里添加的方法和DaggerAppComponent
生成的代码很像?没错Dagger默认实例化AppComponent
就是以这种代码进行的。
不过,对于咱们这个AppModule
来讲,咱们不须要关系它是怎么初始化(由于咱们只须要它所提供给咱们的依赖)。对于Dagger来讲也是如此: Dagger想要为咱们提供被@Provides
标注的依赖,只须要拥有Application
实例便可。由于只要拥有Application
实例Dagger就有办法实例化AppModule
,直接new便可。
因此这里咱们须要一种方式来告诉Dagger:我要提供给你,在@Module
中须要的内容。对于我们的这个demo来讲,我们须要用一种方式把Dagger所须要的Application
给他。
而作到这一点的就是@BindsInstance
。
按照官网的介绍,此注解用于标识Component Builder/SubComponent Builder中的某个方法,该方法容许将实例绑定到Component中。
因此对于咱们的AppModule
来讲,它只须要提供@Provides
的内容就能够了!,它所须要的,Dagger会按照咱们的“指示”,注入进来。也就是这个样子:
@Module
public class AppModule {
@Provides
@Singleton
// 外部传入Application实例(Dagger会按照咱们的“指示”,注入进来)
public SharedPreferences providePreferences(Application application) {
return application.getSharedPreferences("store", Context.MODE_PRIVATE);
}
}
复制代码
而咱们的AppConponent
这样就能够了:
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
SharedPreferences getSharedPrefs();
@Component.Builder
interface Builder {
AppComponent build();
@BindsInstance
// 此时的application就会被,注入到AppModule的providePreferences方法中
Builder application(Application application);
}
}
复制代码
build事后,咱们初始化DaggerAppComponent
,只需如此写:
DaggerAppComponent appComponent = DaggerAppComponent.builder()
.application(this)
.build();
复制代码
那么Dagger是如何为咱们生成DaggerAppComponent
的呢?
public final class DaggerAppComponent implements AppComponent {
private Provider<Application> applicationProvider;
private Provider<SharedPreferences> providePreferencesProvider;
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
public static AppComponent.Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.applicationProvider = InstanceFactory.create(builder.application);
this.providePreferencesProvider =
DoubleCheck.provider(
AppModule_ProvidePreferencesFactory.create(builder.appModule, applicationProvider));
}
@Override
public void inject(MainActivity mainActivity) {}
@Override
public SharedPreferences getSharedPrefs() {
return providePreferencesProvider.get();
}
private static final class Builder implements AppComponent.Builder {
private AppModule appModule;
private Application application;
@Override
public AppComponent build() {
if (appModule == null) {
this.appModule = new AppModule();
}
if (application == null) {
throw new IllegalStateException(Application.class.getCanonicalName() + " must be set");
}
return new DaggerAppComponent(this);
}
@Override
public Builder application(Application application) {
this.application = Preconditions.checkNotNull(application);
return this;
}
}
}
复制代码
对于AppModule
来讲,只是简单的new出来,当咱们须要@Provides
时,只是将所需的application
传进去。而咱们的application
以成员变量的身份呆在了DaggerAppComponent
“体内”。
这篇内容,其实并非为了去讲@Component.Builder
和@BindsInstance
。而是尽量的经过它们,来加深你们去Component和Module的理解。去感觉Dagger的实现,更好的去理解依赖注入。对与咱们而言,须要用其形,学其神。
这样咱们才不会受制于框架,而是驾驭框架。