zoukankan      html  css  js  c++  java
  • Dagger2 生成代码学习

      接上一篇文章介绍了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注解的时候生成的代码就比较多了,本来也想捋捋的,但是原理和上面的都是一样的,大家自己去看吧。

  • 相关阅读:
    [leetcode]Length of Last Word
    本周第一天
    本月第一周的第一天
    获取本周的第一天
    PHP实现今天是星期几
    mysql获取相隔时间段的数据
    在mysql中给查询的结果添加序号列
    《岛上书店》
    正则表达式:在大写字母前面加_
    Git忽略文件的三个办法
  • 原文地址:https://www.cnblogs.com/zhuyp1015/p/5122578.html
Copyright © 2011-2022 走看看