接上一篇文章介紹了Dagger2的初步使用,相信剛接觸的人會覺得很奇怪,怎么會有很多自己沒有定義的代碼出現,為什么Component的創建方式是那樣的。為了搞清楚這些東西,我們需要查看一下Dagger2 生成的源代碼。Dagger2 是一個DI框架,通過學習生成的代碼也可以更好的理解Dagger2是如何做依賴注入的。
將上一篇文章中的工程在SublimeText中打開,結構如下圖:

可以看到AppComponent 生成了 DaggerAppComponent,Dagger2的生成規則中,我們自定義的Component生成之后會加上前綴“Dagger”。此外Module中的每個@Provides 方法都會生成一個Factory 類,命名規則也是很規律的。這里Dagger一共為我們生成了6個類:DaggerAppComponent / AppModule_ProvideApplicationFactory /ReposListActivity_MembersInjector / GithubApiModule_ProvideRetrofitFactory / GithubApiModule_ProvideOkHttpClientFactory / GithubApiModule_ProvideGitHubServiceFactory。接下來我們看看這些類具體是什么樣的。
首先來看一下DaggerAppComponent:
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerAppComponent implements AppComponent {
private Provider<Application> provideApplicationProvider;
private Provider<OkHttpClient> provideOkHttpClientProvider;
private Provider<Retrofit> provideRetrofitProvider;
private Provider<GithubApiService> provideGitHubServiceProvider;
private MembersInjector<ReposListActivity> reposListActivityMembersInjector;
private DaggerAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
private void initialize(final Builder builder) {
this.provideApplicationProvider = AppModule_ProvideApplicationFactory.create(builder.appModule);
this.provideOkHttpClientProvider = GithubApiModule_ProvideOkHttpClientFactory.create(builder.githubApiModule);
this.provideRetrofitProvider = GithubApiModule_ProvideRetrofitFactory.create(builder.githubApiModule, provideApplicationProvider, provideOkHttpClientProvider);
this.provideGitHubServiceProvider = GithubApiModule_ProvideGitHubServiceFactory.create(builder.githubApiModule, provideRetrofitProvider);
this.reposListActivityMembersInjector = ReposListActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideGitHubServiceProvider);
}
@Override
public void inject(ReposListActivity activity) {
reposListActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private AppModule appModule;
private GithubApiModule githubApiModule;
private Builder() {
}
public AppComponent build() {
if (appModule == null) {
throw new IllegalStateException("appModule must be set");
}
if (githubApiModule == null) {
this.githubApiModule = new GithubApiModule();
}
return new DaggerAppComponent(this);
}
public Builder appModule(AppModule appModule) {
if (appModule == null) {
throw new NullPointerException("appModule");
}
this.appModule = appModule;
return this;
}
public Builder githubApiModule(GithubApiModule githubApiModule) {
if (githubApiModule == null) {
throw new NullPointerException("githubApiModule");
}
this.githubApiModule = githubApiModule;
return this;
}
}
}
我們在Application中實例化AppComponent的時候是這樣的:
appComponent = DaggerAppComponent.builder() .githubApiModule(new GithubApiModule()) .appModule(new AppModule(this)) .build();
第一次見的時候肯定覺得一團霧水,為什么要這樣寫呢? 通過上面DaggerAppcomponent代碼可以看出,使用了建造者模式。我們回顧一下AppComponent是怎么樣的:
@Component(modules = { AppModule.class, GithubApiModule.class})
public interface AppComponent {
// inject what
void inject(ReposListActivity activity);
}
@component 后面modules包含了兩個類,在生成的DaggerAppComponent 中的內部類 Builder中,AppModule.class 和 GithubApiModule.class 成為了其成員,並且提供了set方法。在Application中實例化DaggerAppComponent的過程中其實就是調用了其set方法來設置依賴。此外在DaggerAppComponent各個@Provides 注解的方法返回類型都是其一個成員變量,並在Initialize()方法中創建。此外還有一個MembersInjector成員,DaggerAppComponent也要負責創建它。
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class ReposListActivity_MembersInjector implements MembersInjector<ReposListActivity> {
private final MembersInjector<BaseActivity> supertypeInjector;
private final Provider<GithubApiService> githubApiServiceProvider;
public ReposListActivity_MembersInjector(MembersInjector<BaseActivity> supertypeInjector, Provider<GithubApiService> githubApiServiceProvider) {
assert supertypeInjector != null;
this.supertypeInjector = supertypeInjector;
assert githubApiServiceProvider != null;
this.githubApiServiceProvider = githubApiServiceProvider;
}
@Override
public void injectMembers(ReposListActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
supertypeInjector.injectMembers(instance);
instance.githubApiService = githubApiServiceProvider.get();
}
public static MembersInjector<ReposListActivity> create(MembersInjector<BaseActivity> supertypeInjector, Provider<GithubApiService> githubApiServiceProvider) {
return new ReposListActivity_MembersInjector(supertypeInjector, githubApiServiceProvider);
}
}
ReposListActivity_MembersInjector 中通過 injectMembers 方法獲取到 ReposListActivity 的實例(對應的就是 ReposListActivityComponent中的inject),然后進行賦值。從這種賦值的方式來看被@Inject注解的注入對象不能是private的。在看賦值是通過 githubAPiServiceProvider.get() 方法獲取的,githubApiServiceProvider是一個工廠類,我們來看看這個工廠類是怎么樣的:
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class GithubApiModule_ProvideGitHubServiceFactory implements Factory<GithubApiService> {
private final GithubApiModule module;
private final Provider<Retrofit> retrofitProvider;
public GithubApiModule_ProvideGitHubServiceFactory(GithubApiModule module, Provider<Retrofit> retrofitProvider) {
assert module != null;
this.module = module;
assert retrofitProvider != null;
this.retrofitProvider = retrofitProvider;
}。
@Override
public GithubApiService get() {
GithubApiService provided = module.provideGitHubService(retrofitProvider.get());
if (provided == null) {
throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
}
return provided;
}
public static Factory<GithubApiService> create(GithubApiModule module, Provider<Retrofit> retrofitProvider) {
return new GithubApiModule_ProvideGitHubServiceFactory(module, retrofitProvider);
}
}
GithubApiModule_ProvideGitHubServiceFactory 類中有兩個成員,一個是提供(@Provides)GithubService 所在的 module 類,一個是創建GithubService方法所需參數的retrofitProvider(從這里可以看出Dagger2需要創建retrofitProvider的工廠)。然后通過 module.provdeGitHubService()方法來創建 GithubApiService實例,這樣最終穿件了在ReposListActivity中注入的依賴實例。
Dagger2 入門有點繞,也沒找到什么系統性的資料,但是可以通過查看框架自動生成的類來加深理解,方便大家使用。使用到dependencies和SubComponent注解的時候生成的代碼就比較多了,本來也想捋捋的,但是原理和上面的都是一樣的,大家自己去看吧。
