Daager2使用介绍(上篇)

Dagger2官网:http://google.github.io/dagger/
Githup地址:https://github.com/google/dagger

Dagger2是一个依赖注入框架,其目的就是将模块之间依赖性降低,也就是解耦。以MVP模式为例,我们把V的业务逻辑都写在P中,通常的做法在V对象中new P,向P的构造方法传入参数。如果P的构造方法改变了,就会影响了到V中的代码,相应也得修改,V与P之间的依赖性太强导致了这种问题。使用dagger2的话,就不会出现这样的问题。声明P的时候用@Inject注解,就会在V中自动注入P对象。即使改变了P的构造方法,也不会影响到V。

在Android 项目上,Daager2有两种使用方式。第一种方式,是适用于所有的Java项目的,Android工程因为是用Java编写的嘛(当然,新的语言Kotlin就先不管了),所以也适用。

dependencies {

  compile 'com.google.dagger:dagger:2.x'

  annotationProcessor 'com.google.dagger:dagger-compiler:2.x'

}

第二种方式,就只适用于Android工程。

dependencies {
    compile 'com.google.dagger:dagger:2.x'

    annotationProcessor 'com.google.dagger:dagger-compiler:2.x'

    compile 'com.google.dagger:dagger-android:2.x'

    compile 'com.google.dagger:dagger-android-support:2.x'

    annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
}

这两种方式,都有annotationProcessor(注解处理器),其作用是在编译时通过注解生成相应的类文件,生成的类文件就在相应的build\generated\source\apt目录下;其相应的jar包在哪?选中一个依赖包,右击选中Library Properties,如下图:

这里写图片描述

这两种方式相对比的话,第二种方式更简便。第一种方式必须为每个需要注入的类写一个对应的Component接口,为了不这么麻烦,可以写一个基类来处理;但是,这种写法是不好的,在之后会说明。今天,先介绍第一种方式。

常用注解

@Inject:在需要依赖的地方使用这个注解,可以用在构造、字段、方法。

@Inject
HitMvpPresenter mHitMvpPresenter;

在HitFragment类中,mHitMvpPresenter在声明的时候,用@Inject标识了;仅仅是这样,编译是会报错的,我们还得在其构造方式也得用@Inject标识,如下:

@Inject
public HitMvpPresenter(DataManager dataManager, BaseActivity baseActivity,@ActivityContext Context context) {
        mRequest = dataManager.getRequest();
        mLocationUtil = dataManager.getLocationManagerService();
        mBaseActivity = baseActivity;
        mContext = context;
}

@Module: 提供依赖的类,必须用这个注解。在构用@Inject标识的类实例的时候,dagger2才知道从哪里去找到构建该类实例所需要的依赖类。比如,上面的HitMvpPresenter的构造方法所需baseActivity、context两个参数。

@Module
public class ActivityModule {

    private BaseActivity mActivity;

    public ActivityModule(BaseActivity activity){
        mActivity = activity;
    }

    @Provides
    BaseActivity provideActivity() {
        return mActivity;
    }

    @Provides
    @ActivityContext
    Context providesContext() {
        return mActivity;
    }
}

@Provide: 在用@Module标识的类中,方法上用这个注解标识,以提供构造对象需要的依赖参数实例。

@Component: 在用@Component标识的接口中,实例化用@Inject标识的类,所需要的依赖就会在@Module标识的类或@Component标识的接口中找。比如,上面的HitMvpPresenter的构造方法所需dataManager就是在@Component标识的接口中找到的。

@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    DataManager dataManager();
}

也就是说@Component的作用就是将@Inject和@Module连接起来。

简单地说了下,这几个常用注解的作用;接下来就是介绍怎么使用了。

使用介绍

demo地址:https://github.com/568240761/Dagger2Demo

@Component

@Retention(RUNTIME)
@Target(TYPE)
@Documented
public @interface Component {

  Class<?>[] modules() default {};

  Class<?>[] dependencies() default {};

  @Target(TYPE)
  @Documented
  @interface Builder {}
}

点开@Component,里面有两个方法和一个注解(在下篇博客的说明)。两个方法都是返回Class数组,也就是说modules、dependencies的赋值可以是多个类文件。

@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    DataManager dataManager();
}
@ActivityScope
@Component(dependencies = ApplicationComponent.class,modules = ActivityModule.class)
public interface ActivityComponent {
    void inject(MovieActivity movieActivity);
    void inject(FilmmakerActivity filmmakerActivity);
    void inject(SortActivity sortActivity);
    void inject(SearchActivity searchActivity);
}

ActivityComponent是依赖于ApplicationComponent的。这有什么用呢?比如,我在ActivityComponent中注入MovieActivity,MovieActivity所依赖的实例会在ActivityModule中找;找不到的时候,就会到ApplicationComponent中找。比如,上面的HitMvpPresenter的构造方法所需dataManager实例就是在ApplicationComponent中找到的

@Singleton与@ActivityScope

@Singleton是由Java提供的,@ActivityScope是我自定义的注解。打开@Singleton与@ActivityScope,如下:

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}

基本一样。它们都有个注解@Scope,@Scope是用来给依赖划定作用域的。在这里@Singleton与@ActivityScope也有这样的作用;还有一个用处,就是用@Scope标识的类或方法,会在注入的Component只存在一个实例,有点相当于单例,后面代码分析。

需要注意的是一个@Scope只能注解一个Component,不能再注解其他的Component,不然会编译不通过。也就是说,@Singleton用在了ApplicationComponent上,就不能再用在ActivityComponent上;而且因为ActivityComponent依赖于ApplicationComponent,所以ActivityComponent需要一个新的@Scope注解,不然也会编译不通过。

@Module

@Module
public class ApplicationModule {

    protected final Application mApplication;

    public ApplicationModule(Application application) {
        mApplication = application;
    }

    @Provides
    Application provideApplication() {
        return mApplication;
    }

    @Provides
    @ApplicationContext
    Context provideContext() {
        return mApplication;
    }

    @Provides
    @Singleton
    Request provideRequest() {
        return new NetworkManagerService().createRetrofit();
    }
}

结合上面的ApplicationComponent类,在ApplicationComponent中就提供了DataManager、Application、Context、Request这四个类的实例;而且在这里提供给所需类的四个实例都是一样的,并不会新生成实例。如果把ApplicationComponent类和provideRequest()上的@Singleton去掉,Application、Context类提供的实例不会改变,而DataManager和Request提供的实例会每次都不同,也就是新生成一个实例;原因会在之后的代码分析说,其实上面也提到了,原因就在于@Scope。

@Module
public class ActivityModule {

    private BaseActivity mActivity;

    public ActivityModule(BaseActivity activity) {
        mActivity = activity;
    }

    @Provides
    BaseActivity provideActivity() {
        return mActivity;
    }

    @Provides
    @ActivityContext
    Context providesContext() {
        return mActivity;
    }
}

在ActivityComponent中注入的类所需的依赖实例,会在ActivityModule和ApplicationComponent查找。

@ApplicationContext与@ActivityContext

在ApplicationModule和ActivityModule中出现了两个自定义的注解,是用来标识Context是来自Application还是Activity的。

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationContext {
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationContext {
}

它们都有@Qualifier,当类的类型不足以鉴别时候,我们就可以使用这个注解标示。
参考博客: 深入理解Java注解类型(@Annotation)

到这,dagger2的配置工作就完成了,在用之前,一定要先编译项目,通过我们下载的注解编译器来自动生成类文件。

先来看项目中MyMovieApplication类

public class MyMovieApplication extends Application {
    private ApplicationComponent mApplicationComponent;

    public static MyMovieApplication get(Context context){
        return (MyMovieApplication) context.getApplicationContext();
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    public ApplicationComponent getApplicationComponent(){
        if(mApplicationComponent == null){
            mApplicationComponent = DaggerApplicationComponent.builder()
                    .applicationModule(new ApplicationModule(this))
                    .build();
        }
        return mApplicationComponent;
    }
}

代码中的DaggerApplicationComponent就是自动生成的类文件。将ApplicationComponent写在Application中,是为了让它的生命周期就和Application是一样的,就不用担心ApplicationComponent被GC清理掉了。

在我的工程中,除了ActivityComponent,还有一个FragmentComponent;它们都分别对应Activity和Fragment。在这,我就以Activity为例来说明。

在官网上,给出的建议是为每一个需要依赖注入的类,新写一个Component。也就说,你有5个Activity需要依赖注入,就需要写5个Component,是不是很麻烦。为了不复制粘贴,我写了个基类来处理(其实,这种写法是不可行的,在后面会进行说明)。

public class DaggerActivity extends BaseActivity {
    private ActivityComponent mActivityComponent;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivityComponent = DaggerActivityComponent.builder()
                .activityModule(new ActivityModule(this))
                .applicationComponent(MyMovieApplication.get(this).getApplicationComponent())
                .build();
    }

    public ActivityComponent activityComponent() {
        return mActivityComponent;
    }
}

因为有的Activity需要依赖注入,有的又不需要,所以又新建了一个类。在代码中DaggerActivityComponent也是自动生成的,其中有个applicationComponent()方法,可以看出ActivityComponent依赖于ApplicationComponent。下面再看个SearchActivity类的代码。

public class SearchActivity extends DaggerActivity implements SearchMvpView {
    @Inject
    SearchMvpPresenter mSearchMvpPresenter;
    @Inject
    MovieRecyclerViewAdapter mMovieRecyclerViewAdapter;
    ...............

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        bindView(this);

        activityComponent().inject(this);
        ........
    }
    .......
}

通过执行activityComponent().inject(this),将SearchActivity注入到ActivityComponent中。代码中mSearchMvpPresenter和mMovieRecyclerViewAdapter的声明都用了注解@Inject,也就是说这两个实例生成所需的依赖都会在ActivityComponent和ApplicationComponent中查找;需要注意的是这两个类的构造器也需要用@Inject标识。以SearchMvpPresenter为例,代码如下:

public class SearchMvpPresenter extends BasePresenter<SearchMvpView> {
    private final Request mRequest;

    @Inject
    public SearchMvpPresenter(DataManager dataManager) {
        mRequest = dataManager.getRequest();
    }

    .......
}

代码中DataManager 的实例是可以在ApplicationComponent中找到的。

第一种方式就介绍完了,但是这种写法是有问题的。从我们写的代码上看是没有问题,而且复用性又好,但如果打开DaggerActivityComponent类文件,你就会发现问题,这个稍后说明。

程序启动后,如下图:
这里写图片描述
每打开一个继承于DaggerActivity或DaggerFragment的页面,都会新建一个ActivityComponent或FragmentComponent。这两个组件的生命周期都与Activity或Fragment一样;Activity或Fragment销毁了,相应的组件也会被回收。

疑问

先回顾一下,出现的两个问题:

如何实现在Component中提供的实例对象不变或者可变的
为什么在基类中统一处理注入类的方式不行

为了说清出第一个问题,稍微改了一下代码,如下:

@Module
public class ApplicationModule {

    .......

    @Provides
    Request provideRequest() {
        return new NetworkManagerService().createRetrofit();
    }
}
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    DataManager dataManager();

    Request request();
}
public class SearchMvpPresenter extends BasePresenter<SearchMvpView> {
    private final Request mRequest;

    @Inject
    public SearchMvpPresenter(Request request){
        mRequest = request;
    }

   .........
}

在ApplicationModule中,将provideRequest()上的@Singleton去掉(Component中提供的实例对象变与不变,其实就跟@Scope有关;DataManager类上有@Singleton,而provideRequest()上没有,就是为了看代码的差异性);在ApplicationComponent中,新增request()(SearchMvpPresenter需要的依赖实例是不会在ApplicationModule中查找的,所有需要在ApplicationComponent中新增request()

DaggerApplicationComponent类文件源码:

public final class DaggerApplicationComponent implements ApplicationComponent {
  private Provider<Request> provideRequestProvider;

  private Provider<DataManager> dataManagerProvider;

  private DaggerApplicationComponent(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.provideRequestProvider =
        ApplicationModule_ProvideRequestFactory.create(builder.applicationModule);

    this.dataManagerProvider =
        DoubleCheck.provider(
            DataManager_Factory.create(
                provideRequestProvider,
                ImageManagerService_Factory.create(),
                LocationManagerService_Factory.create()));
  }

  @Override
  public DataManager dataManager() {
    return dataManagerProvider.get();
  }

  @Override
  public Request request() {
    return provideRequestProvider.get();
  }

  public static final class Builder {
    private ApplicationModule applicationModule;

    private Builder() {}

    public ApplicationComponent build() {
      if (applicationModule == null) {
        throw new IllegalStateException(
            ApplicationModule.class.getCanonicalName() + " must be set");
      }
      return new DaggerApplicationComponent(this);
    }

    public Builder applicationModule(ApplicationModule applicationModule) {
      this.applicationModule = Preconditions.checkNotNull(applicationModule);
      return this;
    }
  }
}

在MyMovieApplication中,通过调用静态builder(),生成一个静态内部类Builder实例;再调用applicationModule(),传入一个ApplicationModule实例;最后调用build()生成DaggerApplicationComponent实例。

DaggerApplicationComponent实现了ApplicationComponent接口,重写了dataManager()request()。这个两个方法分别返回DataManager和Request类性,也就是说依赖于ApplicationComponent的组件需要request与dataManager实例时,就调用这两个方法来获取所需的实例。

@Override
public Request request() {
     return provideRequestProvider.get();
}
private Provider<Request> provideRequestProvider;

Provider是一个接口


public interface Provider<T> {
    T get();
}

provideRequestProvider赋值在initialize()方法中:

private void initialize(final Builder builder) {

    this.provideRequestProvider =
      ApplicationModule_ProvideRequestFactory.create(builder.applicationModule);
.......
  }

进入create(builder.applicationModule)中:

public static Factory<Request> create(ApplicationModule module) {
    return new ApplicationModule_ProvideRequestFactory(module);
  }

返回了ApplicationModule_ProvideRequestFactory实例:

public final class ApplicationModule_ProvideRequestFactory implements Factory<Request> {
  .......
  @Override
  public Request get() {
    return Preconditions.checkNotNull(
        module.provideRequest(), "Cannot return null from a non-@Nullable @Provides method");
  }
  ......
}

ApplicationModule_ProvideRequestFactory实现了Factory,Factory又继承于Provider:

public interface Factory<T> extends Provider<T> {}

所以provideRequestProvider.get(),就是ApplicationModule_ProvideRequestFactory.get()。在get()中又调用了module.provideRequest(),这个module就是我们在MyMovieApplication中,通过applicationModule(),传入ApplicationModule实例,也就说调用的是ApplicationModule类中的provideRequest()

@Provides
Request provideRequest() {
        return new NetworkManagerService().createRetrofit();
    }

所以,每次调用provideRequest(),都会new个新实例。我们再来看看dataManager()

@Override
public DataManager dataManager() {
    return dataManagerProvider.get();
}

dataManagerProvider赋值与provideRequestProvider有两处不一样;

this.dataManagerProvider =
        DoubleCheck.provider(
            DataManager_Factory.create(
                provideRequestProvider,
                ImageManagerService_Factory.create(),
                LocationManagerService_Factory.create()));

多了个DoubleCheck.provider()方法(待会说明);在DataManager_Factory类中get()方法的实现也不同。

@Override
public DataManager get() {
     return new DataManager(
           requestProvider.get(),
           imageManagerServiceProvider.get(),
           locationManagerServiceProvider.get());
}

直接调用DataManager的构造方法来构建实例;为什么会这样,其原因是DataManager的构造方法上用了@Inject。

@Singleton
public class DataManager {
    @Inject
    public DataManager(Request request, ImageManagerService imageManagerService, LocationManagerService locationManagerService) {
            mRequest = request;
            mImageManagerService = imageManagerService;
            mLocationManagerService = locationManagerService;
    }
}

也就是说在dagger2有两种方式提供实例,一种是通过@Provides标识的方法返回实例,一种是用@Inject标识的构造方法来构造实例。如果,这两种方式都没有,就会编译报错。

来看看DoubleCheck.provider()是干什么?为了说明,我们再把@Singleton加上在provideRequest()上,看看代码有什么不一样。

@Provides
@Singleton
Request provideRequest() {
        return new NetworkManagerService().createRetrofit();
}

clean项目后,再重新编译。

this.provideRequestProvider =
        DoubleCheck.provider(         ApplicationModule_ProvideRequestFactory.create(builder.applicationModule));

除了provideRequestProvider赋值有点变化,也多了个DoubleCheck.provider()方法。其它地方一模一样,这个DoubleCheck是什么?

public final class DoubleCheck<T> implements Provider<T>, Lazy<T> {
  private static final Object UNINITIALIZED = new Object();

  private volatile Provider<T> provider;
  private volatile Object instance = UNINITIALIZED;

  private DoubleCheck(Provider<T> provider) {
    assert provider != null;
    this.provider = provider;
  }

  @SuppressWarnings("unchecked") // cast only happens when result comes from the provider
  @Override
  public T get() {
    Object result = instance;
    if (result == UNINITIALIZED) {
      synchronized (this) {
        result = instance;
        if (result == UNINITIALIZED) {
          result = provider.get();
          Object currentInstance = instance;
          if (currentInstance != UNINITIALIZED && currentInstance != result) {
            throw new IllegalStateException("....");
          }
          instance = result;
          provider = null;
        }
      }
    }
    return (T) result;
  }
  public static <T> Provider<T> provider(Provider<T> delegate) {
    checkNotNull(delegate);
    if (delegate instanceof DoubleCheck) {
      return delegate;
    }
    return new DoubleCheck<T>(delegate);
  }
  ........
}

DoubleCheck也实现Provider,所以调用provideRequestProvider.get(),就是调用DoubleCheck中的get()。在DoubleCheck中的get()中,又对Request实例进行了缓存;所以多次调用DaggerApplicationComponent中request(),返回的都是同一个实例。要想Component中提供的实例对象不变,就使用@Scope;提供的实例对象变化,就不用@Scope就行。

对于第二问题,我们先看生成的DaggerActivityComponent类文件的源码:

public final class DaggerActivityComponent implements ActivityComponent {
  private Provider<BaseActivity> provideActivityProvider;

  private Provider<DataManager> dataManagerProvider;

  private Provider<MovieMvpPresenter> movieMvpPresenterProvider;

  private Provider<FilmmakerRecyclerViewAdapter> filmmakerRecyclerViewAdapterProvider;

  private MembersInjector<MovieActivity> movieActivityMembersInjector;

  private Provider<FilmmakerMvpPresenter> filmmakerMvpPresenterProvider;

  private Provider<MovieRecyclerViewAdapter> movieRecyclerViewAdapterProvider;

  private MembersInjector<FilmmakerActivity> filmmakerActivityMembersInjector;

  private Provider<com.ly.mymovie.ui.adapter.MovieRecyclerViewAdapter>
      movieRecyclerViewAdapterProvider2;

  private Provider<SortMvpPresenter> sortMvpPresenterProvider;

  private MembersInjector<SortActivity> sortActivityMembersInjector;

  private Provider<SearchMvpPresenter> searchMvpPresenterProvider;

  private MembersInjector<SearchActivity> searchActivityMembersInjector;

  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.dataManagerProvider =
        new com_ly_mymovie_injection_component_ApplicationComponent_dataManager(
            builder.applicationComponent);

    this.movieMvpPresenterProvider =
        MovieMvpPresenter_Factory.create(
            MembersInjectors.<MovieMvpPresenter>noOp(),
            provideActivityProvider,
            dataManagerProvider);

    this.filmmakerRecyclerViewAdapterProvider =
        FilmmakerRecyclerViewAdapter_Factory.create(
            MembersInjectors.<FilmmakerRecyclerViewAdapter>noOp(),
            dataManagerProvider,
            provideActivityProvider);

    this.movieActivityMembersInjector =
        MovieActivity_MembersInjector.create(
            movieMvpPresenterProvider, filmmakerRecyclerViewAdapterProvider);

    this.filmmakerMvpPresenterProvider =
        FilmmakerMvpPresenter_Factory.create(
            MembersInjectors.<FilmmakerMvpPresenter>noOp(),
            provideActivityProvider,
            dataManagerProvider);

    this.movieRecyclerViewAdapterProvider =
        MovieRecyclerViewAdapter_Factory.create(
            MembersInjectors.<MovieRecyclerViewAdapter>noOp(),
            dataManagerProvider,
            provideActivityProvider);

    this.filmmakerActivityMembersInjector =
        FilmmakerActivity_MembersInjector.create(
            filmmakerMvpPresenterProvider, movieRecyclerViewAdapterProvider);

    this.movieRecyclerViewAdapterProvider2 =
        com.ly.mymovie.ui.adapter.MovieRecyclerViewAdapter_Factory.create(
            MembersInjectors.<com.ly.mymovie.ui.adapter.MovieRecyclerViewAdapter>noOp(),
            provideActivityProvider,
            dataManagerProvider);

    this.sortMvpPresenterProvider =
        SortMvpPresenter_Factory.create(
            MembersInjectors.<SortMvpPresenter>noOp(), dataManagerProvider);

    this.sortActivityMembersInjector =
        SortActivity_MembersInjector.create(
            movieRecyclerViewAdapterProvider2, sortMvpPresenterProvider);

    this.searchMvpPresenterProvider =
        SearchMvpPresenter_Factory.create(
            MembersInjectors.<SearchMvpPresenter>noOp(), dataManagerProvider);

    this.searchActivityMembersInjector =
        SearchActivity_MembersInjector.create(
            searchMvpPresenterProvider, movieRecyclerViewAdapterProvider2);
  }

  @Override
  public void inject(MovieActivity movieActivity) {
    movieActivityMembersInjector.injectMembers(movieActivity);
  }

  @Override
  public void inject(FilmmakerActivity filmmakerActivity) {
    filmmakerActivityMembersInjector.injectMembers(filmmakerActivity);
  }

  @Override
  public void inject(SortActivity sortActivity) {
    sortActivityMembersInjector.injectMembers(sortActivity);
  }

  @Override
  public void inject(SearchActivity searchActivity) {
    searchActivityMembersInjector.injectMembers(searchActivity);
  }

  public static final class Builder {
    private ActivityModule activityModule;

    private ApplicationComponent applicationComponent;

    private Builder() {}

    public ActivityComponent build() {
      if (activityModule == null) {
        throw new IllegalStateException(ActivityModule.class.getCanonicalName() + " must be set");
      }
      if (applicationComponent == null) {
        throw new IllegalStateException(
            ApplicationComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerActivityComponent(this);
    }

    public Builder activityModule(ActivityModule activityModule) {
      this.activityModule = Preconditions.checkNotNull(activityModule);
      return this;
    }

    public Builder applicationComponent(ApplicationComponent applicationComponent) {
      this.applicationComponent = Preconditions.checkNotNull(applicationComponent);
      return this;
    }
  }

  private static class com_ly_mymovie_injection_component_ApplicationComponent_dataManager
      implements Provider<DataManager> {
    private final ApplicationComponent applicationComponent;

    com_ly_mymovie_injection_component_ApplicationComponent_dataManager(
        ApplicationComponent applicationComponent) {
      this.applicationComponent = applicationComponent;
    }

    @Override
    public DataManager get() {
      return Preconditions.checkNotNull(
          applicationComponent.dataManager(),
          "Cannot return null from a non-@Nullable component method");
    }
  }
}

这个类文件中,有13个成员变量。每打开一个Activity页面,都会new一个DaggerActivityComponent,在initialize()方法会为这13个成员变量赋值,13个成员变量在某个Acitivity中,能用到的只有几个。比如,在SearchActivity中,只有searchMvpPresenterProvider、movieRecyclerViewAdapterProvider2、searchActivityMembersInjector这3个成员变量有用,其他的根本用不到。我这个工程,将所有的Activity都写在ActivityComponent中,随Activity的增多,成员变量会越来越多,这样会很占内存;所以在基类中统一处理注入类的方式是不可取。

那如何避免这个问题?最简单的,就是为每一个Activity新建一个Component。

DaggerActivityComponent.builder()
                .activityModule(new ActivityModule(this))
                .applicationComponent(MyMovieApplication.get(this)
                .getApplicationComponent())
                .build()
                .inject(this);

以上这样的相似代码就复制粘贴呗;但是这样做的话,代码在以后是很难重构;最严重的是它违背了依赖注入的核心原则:一个类不应该知道它是如何被注入的。所以,第一种方式用在Android工程上是不可行的。第二种方式的介绍,我会过几天码。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值