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

前端之家收集整理的这篇文章主要介绍了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(),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<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

猜你在找的设计模式相关文章