Dagger2 彻底了解如何构建依赖关系

Dagger2 彻底了解如何构建依赖关系

上两篇文章分别介绍了Dagger2的使用方式及其一些细节上的知识补充,如果没有看过的,请传送:

这两篇文章知识讲解了如何使用Dagger2的方式,知其然不知其所以然,这篇文章就基于上两篇文章的例子来介绍一下Dagger2通过APT生成的代码,深入了解一下。它是如何工作的,如何注入成员变量的。

本篇内容包括:

  • 回顾代码
  • 一步一步分析注入的过程。
回顾代码:

我们为了定义一个提供全局单例的对象而创建的ComponentModule

//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接口,然后声明管理的moduleApiModule,它提供三个方法,分别是: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对象,然后调用apiModuleApiModule对象传到了BuilderapiModule成员变量上面,然后我们会调用Builderbuild方法,返回的是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方法是对provideOkHttpClientProviderprovideRetrofitProviderprovideUserProvider这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_ProvideRetrofitFactoryApiModule_ProvideUserFactory是一样的实现。

分析到这里我们总体上可以得出一个大致的架子:DaggerAppComponent持有了几个Provider<T>分别用来提供OkHttpClientRetrofitUser对象的(这里有几个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(), "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);
  }

这里就比较多代码了,其实总的来说是为几个Provider<T>赋值,他们分别为:provideActivityProviderprovideDaggerPresenterProvidergetUserProvidergetClientProvidergetRetrofitProviderdaggerActivityMembersInjector。一个一个来说。首先ActivityModule提供了activityDaggerPresenterprovideXXX方法,所以这里我们好理解,这些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是通过builderappComponentgetRetrofit方法来获取的。所以我们在构建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<OkHttpClient> clientProvider,
      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>分别为:presenterProviderclientProviderretrofitProvider。这是因为我在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);
  }

这个是调用了injectorinjectMembers方法,我们看回上面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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值