Dagger2 彻底了解如何构建依赖关系
上两篇文章分别介绍了Dagger2
的使用方式及其一些细节上的知识补充,如果没有看过的,请传送:
这两篇文章知识讲解了如何使用Dagger2
的方式,知其然不知其所以然,这篇文章就基于上两篇文章的例子来介绍一下Dagger2
通过APT
生成的代码,深入了解一下。它是如何工作的,如何注入成员变量的。
- 回顾代码
- 一步一步分析注入的过程。
回顾代码:
我们为了定义一个提供全局单例的对象而创建的Component
和Module
:
//module code
@Module
public class ApiModule {
public static final String END_POINT = "http://www.baidu.com";
@Provides
@Singleton
OkHttpClient provideOkHttpClient() {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60 * 1000,TimeUnit.MILLISECONDS)
.readTimeout(60 * 1000,TimeUnit.MILLISECONDS)
.build();
return client;
}
@Provides
@Singleton
Retrofit provideRetrofit(OkHttpClient client) {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(END_POINT)
.build();
return retrofit;
}
@Provides
@Singleton
User provideUser(){
return new User("name form ApiProvide");
}
}
----------------------------------分割线-----------------------------------------------
//Component code
@Singleton
@Component(modules = {ApiModule.class})
public interface AppComponent {
OkHttpClient getClient();
Retrofit getRetrofit();
User getUser();
}
这里是一个AppComponent
接口,然后声明管理的module
是ApiModule
,它提供三个方法,分别是:getClient()
、getRetrofit()
、getUser()
Make Project
之后,我们在Application
中使用:
AppComponent appComponent;
@Override
public void onCreate() {
super.onCreate();
appComponent = DaggerAppComponent.builder()
.apiModule(new ApiModule())
.build();
}
public AppComponent getAppComponent() {
return appComponent;
}
现在我们打开app
目录下build->generated->source->apt->debug
看看Dagger2
为我们生成的代码吧。首先我们看DaggerAppComponent
的源码:
public final class DaggerAppComponent implements AppComponent {
private Provider<OkHttpClient> provideOkHttpClientProvider;
private Provider<Retrofit> provideRetrofitProvider;
private Provider<User> provideUserProvider;
private DaggerAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static AppComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideOkHttpClientProvider =
DoubleCheck.provider(ApiModule_ProvideOkHttpClientFactory.create(builder.apiModule));
this.provideRetrofitProvider =
DoubleCheck.provider(
ApiModule_ProvideRetrofitFactory.create(
builder.apiModule,provideOkHttpClientProvider));
this.provideUserProvider =
DoubleCheck.provider(ApiModule_ProvideUserFactory.create(builder.apiModule));
}
@Override
public OkHttpClient getClient() {
return provideOkHttpClientProvider.get();
}
@Override
public Retrofit getRetrofit() {
return provideRetrofitProvider.get();
}
@Override
public User getUser() {
return provideUserProvider.get();
}
public static final class Builder {
private ApiModule apiModule;
private Builder() {}
public AppComponent build() {
if (apiModule == null) {
this.apiModule = new ApiModule();
}
return new DaggerAppComponent(this);
}
public Builder apiModule(ApiModule apiModule) {
this.apiModule = Preconditions.checkNotNull(apiModule);
return this;
}
}
}
可以看到这个DaggerAppComponent
实现了我们定义的AppComponent
接口,然后我们一步一步来看,首先我们在Applicaiotn中
调用了如下代码:
appComponent = DaggerAppComponent.builder()
.apiModule(new ApiModule())
.build();
可以看到,通过DaggerAppComponent.builder()
方法得到一个Builder
对象,然后调用apiModule
把ApiModule
对象传到了Builder
的apiModule
成员变量上面,然后我们会调用Builder
的build
方法,返回的是new DaggerAppComponent(this)
,看看这句代码做了什么事情,我们看回上面的代码DaggerAppComponent
的构造函数中,会调用了initialize(builder)
方法,这个方法是干什么的?继续看下去:
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideOkHttpClientProvider =
DoubleCheck.provider(ApiModule_ProvideOkHttpClientFactory.create(builder.apiModule));
this.provideRetrofitProvider =
DoubleCheck.provider(
ApiModule_ProvideRetrofitFactory.create(
builder.apiModule,provideOkHttpClientProvider));
this.provideUserProvider =
DoubleCheck.provider(ApiModule_ProvideUserFactory.create(builder.apiModule));
}
可以明显看到,这个initialize
方法是对provideOkHttpClientProvider
、provideRetrofitProvider
、provideUserProvider
这3个成员变量赋值,这三个成员变量的类型都是Provider<T>
.
然后我们会发现这3个成员变量需要使用ApiModule_ProvideXXXFactory.create(builder.apiModule)
来创建,我们点开其中一个(ApiModule_ProvideOkHttpClientFactory)
看看源码。
public final class ApiModule_ProvideOkHttpClientFactory implements Factory<OkHttpClient> {
private final ApiModule module;
public ApiModule_ProvideOkHttpClientFactory(ApiModule module) {
assert module != null;
this.module = module;
}
@Override
public OkHttpClient get() {
return Preconditions.checkNotNull(
module.provideOkHttpClient(),"Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<OkHttpClient> create(ApiModule module) {
return new ApiModule_ProvideOkHttpClientFactory(module);
}
}
可以看到,这个类是实现了一个Factory<T>
接口的,这个接口其实是继承自Provider<T>
接口,并且里面什么内容都没有的。
我们看看他的create
方法,其实就会返回一个ApiModule_ProvideOkHttpClientFactory
对象,而且是实现了Provider<T>
接口,这个接口只有一个get
方法,get
方法调用就是我们自己编写的module
中的provideXXX
方法(根据返回值标识)。
我们看了一个Facttoy
了,然后后面的ApiModule_ProvideRetrofitFactory
、ApiModule_ProvideUserFactory
是一样的实现。
分析到这里我们总体上可以得出一个大致的架子:DaggerAppComponent
持有了几个Provider<T>
分别用来提供OkHttpClient
、Retrofit
、User
对象的(这里有几个Provider
是看你在AppComponent
中暴露出多少个对象),并且实现了AppComponent
的几个方法,如下:
@Override
public OkHttpClient getClient() {
return provideOkHttpClientProvider.get();
}
@Override
public Retrofit getRetrofit() {
return provideRetrofitProvider.get();
}
@Override
public User getUser() {
return provideUserProvider.get();
}
这写的几个方法都是属于暴露出去的,用来让依赖它的Component
获取对应的对象
分析完AppComponent
之后,我们接下来分析ActivityComponent
了。
//Component code
@ActivityScope
@Component(modules = ActivityModule.class,dependencies = AppComponent.class)
public interface ActivityComponent {
void inject(DaggerActivity daggerActivity);
}
----------------------------------分割线-----------------------------------------------
//module code
@Module
public class ActivityModule {
private DaggerActivity activity;
public ActivityModule(DaggerActivity activity) {
this.activity = activity;
}
@Provides
public DaggerActivity provideActivity() {
return activity;
}
@Provides
public DaggerPresenter provideDaggerPresenter(DaggerActivity activity,User user) {
return new DaggerPresenter(activity,user);
}
}
我们看看在Activity
中做了什么操作:
@Inject
DaggerPresenter presenter;
@Inject
OkHttpClient client;
@Inject
Retrofit retrofit;
private void inject() {
AppComponent appComponent = ((MyApplication) getApplication()).getAppComponent();
DaggerActivityComponent.builder()
.appComponent(appComponent)
.activityModule(new ActivityModule(this))
.build().inject(this);
}
我们先从DaggerActivityComponent
的代码看起:
public final class DaggerActivityComponent implements ActivityComponent {
private Provider<DaggerActivity> provideActivityProvider;
private Provider<User> getUserProvider;
private Provider<DaggerPresenter> provideDaggerPresenterProvider;
private Provider<OkHttpClient> getClientProvider;
private Provider<Retrofit> getRetrofitProvider;
private MembersInjector<DaggerActivity> daggerActivityMembersInjector;
private DaggerActivityComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideActivityProvider =
ActivityModule_ProvideActivityFactory.create(builder.activityModule);
this.getUserProvider =
new Factory<User>() {
private final AppComponent appComponent = builder.appComponent;
@Override
public User get() {
return Preconditions.checkNotNull(
appComponent.getUser(),"Cannot return null from a non-@Nullable component method");
}
};
this.provideDaggerPresenterProvider =
ActivityModule_ProvideDaggerPresenterFactory.create(
builder.activityModule,provideActivityProvider,getUserProvider);
this.getClientProvider =
new Factory<OkHttpClient>() {
private final AppComponent appComponent = builder.appComponent;
@Override
public OkHttpClient get() {
return Preconditions.checkNotNull(
appComponent.getClient(),"Cannot return null from a non-@Nullable component method");
}
};
this.getRetrofitProvider =
new Factory<Retrofit>() {
private final AppComponent appComponent = builder.appComponent;
@Override
public Retrofit get() {
return Preconditions.checkNotNull(
appComponent.getRetrofit(),"Cannot return null from a non-@Nullable component method");
}
};
this.daggerActivityMembersInjector =
DaggerActivity_MembersInjector.create(
provideDaggerPresenterProvider,getClientProvider,getRetrofitProvider);
}
@Override
public void inject(DaggerActivity daggerActivity) {
daggerActivityMembersInjector.injectMembers(daggerActivity);
}
public static final class Builder {
private ActivityModule activityModule;
private AppComponent appComponent;
private Builder() {}
public ActivityComponent build() {
if (activityModule == null) {
throw new IllegalStateException(ActivityModule.class.getCanonicalName() + " must be set");
}
if (appComponent == null) {
throw new IllegalStateException(AppComponent.class.getCanonicalName() + " must be set");
}
return new DaggerActivityComponent(this);
}
public Builder activityModule(ActivityModule activityModule) {
this.activityModule = Preconditions.checkNotNull(activityModule);
return this;
}
public Builder appComponent(AppComponent appComponent) {
this.appComponent = Preconditions.checkNotNull(appComponent);
return this;
}
}
}
DaggerActivityComponent.builder()
.appComponent(appComponent)
.activityModule(new ActivityModule(this))
.build().inject(this);
看看我们到底做了什么操作,首先调用builder
方法创建一个Builder
对象,然后把上面分析的appComponent
传入到Buidler
对象的appComponent
成员中,再传入activityModule
,之后调用一下build
方法,返回一个new DaggerActivityComponent(this)
对象,然后调用initialize(builder)
方法,(这个过程是不是和上面AppComponent
的非常相似呢?哈哈),我们来看看initialize
方法做了什么事:
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideActivityProvider =
ActivityModule_ProvideActivityFactory.create(builder.activityModule);
this.getUserProvider =
new Factory<User>() {
private final AppComponent appComponent = builder.appComponent;
@Override
public User get() {
return Preconditions.checkNotNull(
appComponent.getUser(),getRetrofitProvider);
}
这里就比较多代码了,其实总的来说是为几个Provider<T>
赋值,他们分别为:provideActivityProvider
、provideDaggerPresenterProvider
、getUserProvider
、getClientProvider
、getRetrofitProvider
、daggerActivityMembersInjector
。一个一个来说。首先ActivityModule
提供了activity
和DaggerPresenter
的provideXXX
方法,所以这里我们好理解,这些Provider<T>
的初始化我们上面已经说过了。
值得注意的是,我们ActivtyComponent
依赖了AppComponent
,并且使用了AppComponent
提供的成员,我们随便看一个。比如:
this.getRetrofitProvider =
new Factory<Retrofit>() {
private final AppComponent appComponent = builder.appComponent;
@Override
public Retrofit get() {
return Preconditions.checkNotNull(
appComponent.getRetrofit(),"Cannot return null from a non-@Nullable component method");
}
};
可以看到,这个getRetrofitProvider
是通过builder
的appComponent
的getRetrofit
方法来获取的。所以我们在构建DaggerActivityComponent
的时候要调用一下appComponent(appComponent)
方法,把我们之前创建出来的AppComponent
对象传进来用于提供依赖。
最后我还有一个没有说,就是daggerActivityMembersInjector
是什么东西呢?请注意这个才是实现依赖注入真正关键的一步,经过我的测试,在DaggerActivity
中只有使用了@Inject
注解的情况下,才会在DaggerActivityComponent
中自动生成一个成员变量:
MembersInjector<DaggerActivity> daggerActivityMembersInjector;
我们来看这个东西的实例化方式:
public final class DaggerActivity_MembersInjector implements MembersInjector<DaggerActivity> {
private final Provider<DaggerPresenter> presenterProvider;
private final Provider<OkHttpClient> clientProvider;
private final Provider<Retrofit> retrofitProvider;
public DaggerActivity_MembersInjector(
Provider<DaggerPresenter> presenterProvider,Provider<OkHttpClient> clientProvider,Provider<Retrofit> retrofitProvider) {
assert presenterProvider != null;
this.presenterProvider = presenterProvider;
assert clientProvider != null;
this.clientProvider = clientProvider;
assert retrofitProvider != null;
this.retrofitProvider = retrofitProvider;
}
public static MembersInjector<DaggerActivity> create(
Provider<DaggerPresenter> presenterProvider,Provider<Retrofit> retrofitProvider) {
return new DaggerActivity_MembersInjector(presenterProvider,clientProvider,retrofitProvider);
}
@Override
public void injectMembers(DaggerActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.presenter = presenterProvider.get();
instance.client = clientProvider.get();
instance.retrofit = retrofitProvider.get();
}
public static void injectPresenter(
DaggerActivity instance,Provider<DaggerPresenter> presenterProvider) {
instance.presenter = presenterProvider.get();
}
public static void injectClient(DaggerActivity instance,Provider<OkHttpClient> clientProvider) {
instance.client = clientProvider.get();
}
public static void injectRetrofit(DaggerActivity instance,Provider<Retrofit> retrofitProvider) {
instance.retrofit = retrofitProvider.get();
}
}
可以看到,它持有3个Provider<T>
分别为:presenterProvider
、clientProvider
、retrofitProvider
。这是因为我在DaggerActivity
中只为3个成员变量添加了@Inject
注解,事实上你用了多少个@Inject
,这个DaggerActivity_MembersInjector
会有多少个Provider<T>
。这些Provider<T>
都是在initialize方法中进行赋值的。
好了源码分析的差不多了,我们来看看最后一步。之前也提过疑问,我们为什么要在ActivityComponent
中添加一个inject方法呢,并且他的参数一定要是DaggerActivity
,现在到了揭晓的时刻了。
我们来看看生成的DaggerActivityComponent
中的inject
方法:
@Override
public void inject(DaggerActivity daggerActivity) {
daggerActivityMembersInjector.injectMembers(daggerActivity);
}
这个是调用了injector
的injectMembers
方法,我们看回上面DaggerActivity_MembersInjector
的代码中的injectMembers
方法:
@Override
public void injectMembers(DaggerActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.presenter = presenterProvider.get();
instance.client = clientProvider.get();
instance.retrofit = retrofitProvider.get();
}
看到了吗,我们传进来的DaggerActivity
中的那3个添加了@Inject
注解的成员都通过对应的Provider<T>
的get
方法获取了实例。这样就完成了赋值的操作了,依赖注入就完成了。
总结
对于Dagger2的依赖原理分析了一边,如果看的过程中有些疑问的话,请仔细看代码,其实思路还是很清晰的,肯花点事件就可以了。大家可以通过以下链接获取源码来更深入的了解。
源码地址:https://github.com/Jamlh/Sample/tree/master/app/src/main/java/com/sample/dagger