Dagger2 生成代碼學習

  接上一篇文章介紹了Dagger2的初步使用,相信剛接觸的人會以爲很奇怪,怎麼會有不少本身沒有定義的代碼出現,爲何Component的建立方式是那樣的。爲了搞清楚這些東西,咱們須要查看一下Dagger2 生成的源代碼。Dagger2 是一個DI框架,經過學習生成的代碼也能夠更好的理解Dagger2是如何作依賴注入的。html

  將上一篇文章中的工程在SublimeText中打開,結構以下圖:git

  能夠看到AppComponent 生成了 DaggerAppComponent,Dagger2的生成規則中,咱們自定義的Component生成以後會加上前綴「Dagger」。此外Module中的每一個@Provides 方法都會生成一個Factory 類,命名規則也是很規律的。這裏Dagger一共爲咱們生成了6個類:DaggerAppComponent / AppModule_ProvideApplicationFactory /ReposListActivity_MembersInjector / GithubApiModule_ProvideRetrofitFactory / GithubApiModule_ProvideOkHttpClientFactory / GithubApiModule_ProvideGitHubServiceFactory。接下來咱們看看這些類具體是什麼樣的。github

  首先來看一下DaggerAppComponent:app

@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是怎麼樣的:ide

@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是一個工廠類,咱們來看看這個工廠類是怎麼樣的:ui

@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中注入的依賴實例。this

  Dagger2 入門有點繞,也沒找到什麼系統性的資料,可是能夠經過查看框架自動生成的類來加深理解,方便你們使用。使用到dependencies和SubComponent註解的時候生成的代碼就比較多了,原本也想捋捋的,可是原理和上面的都是同樣的,你們本身去看吧。spa

相關文章
相關標籤/搜索