Dagger2使用

一、什么是依赖注入

依赖注入(Dependency Injection,简称 DI) 是用于实现控制反转Inversion of Control,缩写为 IoC)的最常见的方式之一。
控制反转是面向对象变成中的一种设计院子,用以降低代码之间的耦合度。控制反转的基本思想是:借助“第三方”实现具有依赖关系的对象之间的解耦。一开始是对象A对对象B具有依赖关系,对象A主动地创建对象B,对象A有主动控制权,实现了IOC后,对象A依赖于Ioc容器,对象A被动地接受IOC容器提供的对象B实例,由主动变被动。

依赖注入就是将一个对象的实例传入到另一个对象中去。依赖注入是一种设计模式,降低依赖和被依赖对象之间的耦合,方便扩展和单元测试。

依赖注入的常见实现方式:

  • 基于构造函数,在构造对象时注入所依赖的对象
public class Police {
    public Police(Gun gun){
        this.gun = gun;
    }
}

  • 基于set方法,让外部容器传入所依赖的实例
public class Police {
    public void setGun(Gun gun){
        this.gun = gun;
    }
}

  • 基于接口,使用接口setter方法提供
public class Police implements GunInjector{

    @Override
    public void injectCar(Gun gun) {
        this.gun = gun
    }
}

  • 基于注解实现,如Dagger2 的@Inject注解
public class Police {
    @Inject
    Gun gun;
}

Dagger2依赖注入的基本使用

引入Dagger2

在build.gradle中添加依赖

   //dagger 2
    implementation 'com.google.dagger:dagger:2.16'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.16'

Dagger2 依赖注入的构成:

image.png

1、目标类中 需要注入的实例 用@Inject标注。

如下,Police类中的属性Gun 和 Uniform需要注入。

public class Police {
    @Inject
    Gun gun;

    @Inject
    Uniform uniform;

}

对象会生成Police_MembersInjector类,继承自MembersInjector,其中injectMembers()完成Gun和Uniform的注入。

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class Police_MembersInjector implements MembersInjector {
  private final Provider gunProvider;

  private final Provider uniformProvider;

  public Police_MembersInjector(Provider gunProvider, Provider uniformProvider) {
    this.gunProvider = gunProvider;
    this.uniformProvider = uniformProvider;
  }

  public static MembersInjector create(
      Provider gunProvider, Provider uniformProvider) {
    return new Police_MembersInjector(gunProvider, uniformProvider);
  }

  @Override
  public void injectMembers(Police instance) {
    injectGun(instance, gunProvider.get());
    injectUniform(instance, uniformProvider.get());
  }

  public static void injectGun(Police instance, Gun gun) {
    instance.gun = gun;
  }

  public static void injectUniform(Police instance, Uniform uniform) {
    instance.uniform = uniform;
  }
}

2、提供依赖对象实例的工厂类。

有两种方式:

(1)用@Inject 标注构造函数,提供被依赖对象的工厂类。

public class Gun {
    @Inject
    public Gun(){

    }
}

对应会生成Gun_Factory工厂类,通过get()方法产生依赖对象实例

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class Gun_Factory implements Factory {
  private static final Gun_Factory INSTANCE = new Gun_Factory();

  @Override
  public Gun get() {
    return provideInstance();
  }

  public static Gun provideInstance() {
    return new Gun();
  }

  public static Gun_Factory create() {
    return INSTANCE;
  }

  public static Gun newGun() {
    return new Gun();
  }
}

(2)通过 @Moudle 和@Providers注解配合使用。

  • 此方法主要适用于第三方类库 等无法修改构造方法的场景。
  • @Module方式的 要优先于 @inject的方式 注入实例
@Module
public class UniFormModule {
    @Provides
    Uniform provideUniform(){
        return new Uniform();
    }
}


public class Uniform {

}

对应会生成UniFormModule_ProvideUniformFactory类,通过get()方法得到。

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class UniFormModule_ProvideUniformFactory implements Factory {
  private final UniFormModule module;

  public UniFormModule_ProvideUniformFactory(UniFormModule module) {
    this.module = module;
  }

  @Override
  public Uniform get() {
    return provideInstance(module);
  }

  public static Uniform provideInstance(UniFormModule module) {
    return proxyProvideUniform(module);
  }

  public static UniFormModule_ProvideUniformFactory create(UniFormModule module) {
    return new UniFormModule_ProvideUniformFactory(module);
  }

  public static Uniform proxyProvideUniform(UniFormModule instance) {
    return Preconditions.checkNotNull(
        instance.provideUniform(), "Cannot return null from a non-@Nullable @Provides method");
  }
}

(3)通过 @Moudle 和@Binds注解 提供注入

@Binds 是@provider的替代。

  • @provider 修饰的方法的方法体必须返回一个实体类。

  • 而 @Binds 修饰的方法A 返回一个接口,方法A 的参数必须是接口的实现类。方法A是抽象的,所以不需有方法体。

  • 同时方法A中的参数(如SplashViewModel) 必须是可以可供注入的(@Module和@Provider方式提供了注入,或者其构造方法添加@Inject方式提供了注入)

@Module
abstract class ViewModelModule {

    @Binds
    abstract fun bindSplashModel(model: SplashViewModel): ViewModel
}

如上声明后,就可以直接获取到SplashViewModel的注入对象了。

另外@Binds 还可以和@IntoMap (或IntoSet)结合使用.
如下所示,注入的SplashViewModel对象会放入到一个Map结构中。
该Map结构 可直接为其他对象提供注入(自动生成的Map对象自动成为可注入对象)。

@Module
abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(SplashViewModel::class)
    abstract fun bindSplashModel(model: SplashViewModel): ViewModel
}

3、提供@Component 修饰的接口XXXComponent接口,并提供inject()注入方法

Component 一方面连接着目标类,另一方面连接着 被依赖对象的工厂类,通过inject()方法将目标类中的对象方法 进行实例注入。


@Component(modules = UniFormModule.class)
public interface PoliceComponent {
    public void inject(Police police);
}

对应生成DaggerPoliceComponent类,DaggerPoliceComponent.Builder类。
通过inject方法,将提供依赖实例的Factory类于目标类对应的属性相关联。


@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerPoliceComponent implements PoliceComponent {
  private UniFormModule uniFormModule;

  private DaggerPoliceComponent(Builder builder) {
    initialize(builder);
  }

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

  public static PoliceComponent create() {
    return new Builder().build();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {
    this.uniFormModule = builder.uniFormModule;
  }

  @Override
  public void inject(Police police) {
    injectPolice(police);
  }

  private Police injectPolice(Police instance) {
    Police_MembersInjector.injectGun(instance, new Gun());
    Police_MembersInjector.injectUniform(
        instance, UniFormModule_ProvideUniformFactory.proxyProvideUniform(uniFormModule));
    return instance;
  }

  public static final class Builder {
    private UniFormModule uniFormModule;

    private Builder() {}

    public PoliceComponent build() {
      if (uniFormModule == null) {
        this.uniFormModule = new UniFormModule();
      }
      return new DaggerPoliceComponent(this);
    }

    public Builder uniFormModule(UniFormModule uniFormModule) {
      this.uniFormModule = Preconditions.checkNotNull(uniFormModule);
      return this;
    }
  }
}

二、几个特殊概念

1、Lazy (延迟注入)

有时我们希望注入的依赖在使用时在完成初始化,可以加快加载速度,这是可以使用Layz。只有在调用Lazy的get()方法时才会初始化依赖实力注入目标类。

public class Man {
    @Inject
    Lazy lazyCar;

    public void goWork() {
        ...
        lazyCar.get().go(); // lazyCar.get() 返回 Car 实例
        ...
    }
}

2、Provider 注入

有时候我们不仅仅是注入单个实例,我们需要多个实例,这是可以使用Provider,每次调用它的get()方法都会调用到@Inject 构造函数 或者Module 的 provide 方法 返回实例

public class CarFactory {
    @Inject
    Provider carProvider;

    public List makeCar(int num) {
        ...
        List carList = new ArrayList(num);
        for (int i = 0; i < num; i ++) {
            carList.add(carProvider.get());
        }
        return carList;
    }
}

3、Qualifier(限定符)

注入迷失问题:
如果 CarModule 提供了两个生成 Car 实例的 provide 方法,Dagger2 就不知道用哪个provider来注入了。这称为注入迷失问题。

@Module
public class CarModule {
    @Provides
    static Car provideCar1() {
        return new Car1();
    }
    @Provides
    static Car provideCar2() {
        return new Car2();
    }
    // Car1 和 Car2 是 Car 的两个子类
}

@Qualifier注解就是用来解决这个问题,使用注解来确定使用哪种 provide 方法。

自定义的@Named注解,你也可以用自定义的其他 Qualifier 注解。

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {
  String value() default "";
}

在 provide 方法上加上@Named注解,用来区分

@Module
public class CarModule {
    @Provides
    @Named("car1")
    static Car provideCar1() {
        return new Car1();
    }
    @Provides
    @Named("car2")
    static Car provideCar2() {
        return new Car2();
    }
}

还需要在 Inject 注入的地方加上@Named注解,表明需要注入的是哪一种 Car:

public class Man {
    @Inject
    @Named("car1")
    Car car;
    ...
}

Qualifier(限定符)的作用相当于起了个区分的别名。

4、Scope(作用域)

Scope 是用来确定注入的实例的生命周期的。
如果没有使用 Scope 注解,Component 每次调用 Module 中的 provide 方法或 Inject 构造函数生成的工厂时都会创建一个新的实例,而使用 Scope 后可以复用之前的依赖实例。

当Component 与 Module、目标类(需要被注入依赖)使用 Scope 注解绑定时,意味着 Component 对象持有绑定的依赖实例的一个引用直到 Component 对象本身被回收。也就是作用域的原理,其实是让生成的依赖实例的生命周期与 Component 绑定,Scope 注解并不能保证生命周期,要想保证赖实例的生命周期,需要确保 Component 的生命周期。

自定义一个Scope

@Documented
@Retention(RUNTIME)
@Scope
public @interface MyScope {}
@Module
public class CarModule {

    @Provides
    @MyScope
    static Car provideCar() {
        return new Car();
    }
}

@MyScope
@Component(modules = CarModule.class)
public interface ManComponent {
    void injectMan(Man man);
}

Module 中 provide 方法中的 Scope 注解必须和 与之绑定的 Component 的 Scope 注解一样,否则作用域不同会导致编译时会报错。

  • Scope 作用域的本质:Component 间接持有依赖实例的引用,把实例的作用域与 Component 绑定,它们不是同年同月同日生,但是同年同月死。
  • Component 可以同时被多个 Scope 标记。即 Component 可以和多个 Scope 的 Moudle 或目标类绑定。

4、Reusable Scope

reusable 可以缓存之前的实例,可以复用之前的实例,不想关心与之绑定是什么 Component。

reusable 作用域不关心绑定的 Component,Reusable 作用域只需要标记目标类或 provide 方法,不用标记 Component。

5、Binding Instances

@BindsInstance注解,只能在 Component.Builder 中使用,用于在创建Component的时候绑定依赖实例。

并且在调用build()创建 Component 之前,所有@BindsInstance方法必须先调用。

@ActivityScope
@Component
public interface HomeActivityComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder activity(Activity activity);
        HomeActivityComponent build();
    }
}

三、Component 的组织关系:(dependencies)依赖关系、(subcomponent)继承关系

1、依赖关系 :一个 Component 依赖其他 Compoent 公开的依赖实例,用 Component 中的dependencies声明。

  • 被依赖的 Component 需要把暴露的依赖实例用显式的接口声明,如上面的Car car(),我们只能使用朋友愿意分享的东西。
  • 依赖关系中的 Component 的 Scope 不能相同,因为它们的生命周期不同。

如下:

@ManScope
@Component(modules = CarModule.class)
public interface ManComponent {
    void inject(Man man);

    Car car();  //必须向外提供 car 依赖实例的接口,表明 Man 可以借 car 给别人
}

@FriendScope
@Component(dependencies = ManComponent.class)
public interface FriendComponent {
    void inject(Friend friend);
}

依赖注入时,需要把被依赖组件(manComponent)的对象 传递到 依赖组件(FriendComponent)中。

ManComponent manComponent = DaggerManComponent.builder()
    .build();

FriendComponent friendComponent = DaggerFriendComponent.builder()
    .manComponent(manComponent)
    .build();
friendComponent.inject(friend);

这样Friend中的car 就和Man中的car时同一个car

2、 继承关系:

一个 Component 继承(也可以叫扩展)某 Component 提供更多的依赖。SubComponent 就是继承关系的体现。

public class Man {
    @Inject
    Car car;
    ...
}

public class Son {
    @Inject
    Car car;

    @Inject
    Bike bike;
}

Son 可以开他爸爸 Man 的车 car,也可以骑自己的自行车 bike。

SonComponent 是在 FatherComponent之中的,SonComponent 子承父业,可以访问 FatherComponent 的依赖。 而FatherComponent 只知道 SonComponent 是它的 child Component,可以访问 SubComponent.Builder,却无法访问 SubComponent 中的依赖。

@Module(subcomponents = SonComponent.class)
public class FatherModule {
    @Provides
    @FatherScope
    static Car provideCar(){
        return new Car();
    }
}


@FatherScope
@Component(modules = FatherModule.class)
public interface FatherComponent {
    void inject(Man man);
    SonComponent.Builder sonComponent();    // 增加一个方法,用来创建 Subcomponent。
}

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


public class Bike {
}


@Module
public class BikeModule {

    @Provides
    @SonScope
    Bike provideBike(){
        return new Bike();
    }
}
public class Son {
    @Inject
    public Car car;

    @Inject
    public Bike bike;
}


@SonScope
@Subcomponent(modules = BikeModule.class)
public interface SonComponent {
    void inject(Son son);

    @Subcomponent.Builder
    interface Builder{
        SonComponent build();
    }
}


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

如何定义Subcomponent?

  • 用@Subcomponent 标记SonComponent类
    -同时SonComponent类中 定义 @Subcomponent.Builder接口,声明SonComponent build();

@SonScope
@Subcomponent(modules = BikeModule.class)
public interface SonComponent {
    void inject(Son son);

    @Subcomponent.Builder
    interface Builder{
        SonComponent build();
    }
}

如何表明SubComponent是属于哪个Parent Component的的?

需要在 parent Component 依赖的 Module 中的subcomponents加上 SubComponent 的 class

@Module(subcomponents = SonComponent.class)
public class FatherModule {
    @Provides
    @FatherScope
    static Car provideCar(){
        return new Car();
    }
}

SubComponent 编译时不会生成 DaggerXXComponent类文件,
其生代码实现位于DaggerFatherComponenet内部,以内部类的形式存在。

public final class DaggerFatherComponent implements FatherComponent {
  private Provider provideCarProvider;

  private DaggerFatherComponent(Builder builder) {
    initialize(builder);
  }

 

  @Override
  public SonComponent.Builder sonComponent() {
    return new SonComponentBuilder();
  }

  private Man injectMan(Man instance) {
    Man_MembersInjector.injectCar(instance, provideCarProvider.get());
    return instance;
  }

  public static final class Builder {
    private Builder() {}

    public FatherComponent build() {
      return new DaggerFatherComponent(this);
    }

    /**
     * @deprecated This module is declared, but an instance is not used in the component. This
     *     method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
     */
    @Deprecated
    public Builder fatherModule(FatherModule fatherModule) {
      Preconditions.checkNotNull(fatherModule);
      return this;
    }
  }

  private final class SonComponentBuilder implements SonComponent.Builder {
    private BikeModule bikeModule;

    @Override
    public SonComponent build() {
      if (bikeModule == null) {
        this.bikeModule = new BikeModule();
      }
      return new SonComponentImpl(this);
    }
  }

  private final class SonComponentImpl implements SonComponent {
    private Provider provideBikeProvider;

    private SonComponentImpl(SonComponentBuilder builder) {
      initialize(builder);
    }

    @SuppressWarnings("unchecked")
    private void initialize(final SonComponentBuilder builder) {
      this.provideBikeProvider =
          DoubleCheck.provider(BikeModule_ProvideBikeFactory.create(builder.bikeModule));
    }

    @Override
    public void inject(Son son) {
      injectSon(son);
    }

    private Son injectSon(Son instance) {
      Son_MembersInjector.injectCar(instance, DaggerFatherComponent.this.provideCarProvider.get());
      Son_MembersInjector.injectBike(instance, provideBikeProvider.get());
      return instance;
    }
  }
}

依赖注入代码:

        Son son = new Son();
        Man man = new Man();

        FatherComponent fatherComponent = DaggerFatherComponent.builder().build();
        SonComponent sonComponent  = fatherComponent.sonComponent().build();
        sonComponent.inject(son);
        fatherComponent.inject(man);
        Log.d("feifei---","father.car:"+man.car.hashCode()+"\n"
            +"son.car:"+son.car.hashCode()
        );

依赖关系 vs 继承关系

相同点:

  • 两者都能复用其他 Component 的依赖
  • 有依赖关系和继承关系的 Component 不能有相同的 Scope

区别点:

  • 依赖关系中被依赖的 Component 必须显式地提供公开依赖实例的接口,而 SubComponent 默认继承 parent Component 的依赖
  • 依赖关系会生成两个独立的 DaggerXXComponent 类,而 SubComponent 不会生成 独立的 DaggerXXComponent 类。

module 之间可以组成include 关系。

一个moduleA可以将另一个moduleB包含进来,拥有moduleB中的所有的provider.

@Module(includes = [ViewModelModule::class])
class AppModule {
    
}

四、 dagger.android的使用

引入dagger.android扩展库

// dagger 2
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"

// dagger.android
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt "com.google.dagger:dagger-android-processor:$dagger_version"

1、定义XXXSubComponent

/**
 * 指定SearchActivitySubcomponent 继承自AndroidInjector接口
 * 指定SearchActivitySubcomponent.Builder 继承自AndroidInjector.Builder
 * SearchActivitySubcomponent 继承自 AppComponent,同时也就继承了AppComponenet中的所有的Provider
 * 包括:AppService、DbService,FlowerBean 还有Application的provider
 */
@Subcomponent(modules = {AndroidInjectionModule.class})
public interface SearchActivitySubcomponent extends AndroidInjector {

    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder{
    }

    AppService providerAppApi();

}

2、定义Application 依赖的module

如下,指定subcomponents 为 1中定义的 SearchActivitySubcomponent.class

用@Binds、@IntoMap、@ActivityKey 注释,指定ActivityModule 提供 AndroidInjector.Factory 的Provider,
并将SearchActivitySubcomponent.class 和SearchActivitySubcomponent.Builder 保存到一个map结构中。

@Module(subcomponents = {SearchActivitySubcomponent.class})
public abstract class ActivityModule {

    /**
     * @Binds的用法:
     *
     *当需要返回的是接口的实例时,需要用到@Binds注解
     * 并要求:
     * (1)方法中必须有参数且只能有一个,是接口的实现类,返回值类型是一个接口
     * (2)实现类必须提供@Inject的构造或Module中的Provides形式提供
     * (3)方法是抽象方法,不必写方法体
     * (4)此时使用@Binds代替@Inject
     */

    /**
     * @IntoMap 是有注入形式初始化 map集合,Map由一系列key-value组成。
     * @ActivityKey(SearchActivity.class)  指定了map中使用的Key,而value为方法的返回值。
     *
     */
    @Binds
    @IntoMap
    @ActivityKey(SearchActivity.class)
    abstract AndroidInjector.Factory bindAndroidInjectorFactory(SearchActivitySubcomponent.Builder builder);

 
    

}

3、把module 安装到AppComponent当中

@Singleton
@Component(modules = {
        AppModule.class,
        ActivityModule.class,
        //YourActivityModule.class,
        AndroidInjectionModule.class,
       })
public interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        public Builder application(Application application);
        public AppComponent  build();
    }

    void inject(MyApp application);

    AppService providerAppApi();

}

4、MyApp 继承HasActivityInjector ,实现activityInjector()方法,

定义并@Inject标记注入DispatchingAndroidInjector当中。

public class MyApp extends Application implements HasActivityInjector {


    @Inject
    public DispatchingAndroidInjector dispatchingActivityInjector;
    @Override
    public void onCreate() {
        super.onCreate();
        DaggerAppComponent.builder().application(this).build().inject(this);
    }

    @Override
    public AndroidInjector activityInjector() {
        return dispatchingActivityInjector;
    }
}

6、最后在 Search的onCreate)() 方法中,在 super.onCreate() 之前调用 AndroidInjection.inject(this)。


public class SearchActivity extends AppCompatActivity {

    @Inject
    AppService appApi;

    @Inject
    DbService dbService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        Log.d("feifei -- ","appApi.hashCode:"+appApi.hashCode());
    }
}

其实也可以在BaseActivity中调用AndroidInjection.inject(this)。

五、Android-dagger2的简化步骤

5.1、dagger的三要素

(1) 原型提供者providers:
  • 构造方法 @Inject标记
public class Car {
    @Inject
    public Car(){
        
    }
}
  • @module + @providers module模块需要与DaggerXXXComponent绑定,告诉 DaggerXXXComponent去哪里取provider
@Module
public class CarModule {

    @Provides
    @ManScope
    static Car provideCar(){
        return new Car();
    }
}
(2)Owner:需要原型的"人"。Owner中需要注入的对象,用@inject标注

main.java

public class Man {
    @Inject
    public Car car;
}

(3) component 装配工人:提供inject(T instance)方法,负责 从providers生产出原型,装备到owner 手中。

ManComponent.java

@Component(modules = CarModule.class)
public interface ManComponent {
    void injectMain(Man man);
}

5.2、注入的触发时机

在特定的时机 调用注入代码:

  Man man = new Man();
        DaggerManComponent.builder().build().injectMain(man);

5.3、android-dagger简化步骤

如果 SubComponent 和其 Builder 没有其他方法或没有继承其他类型,可以使用 @ContributesAndroidInjector

@Module
public abstract class YourActivityModule {

    /** 
    ContributesAndroidInjector 标注会自动生成
     */
@ActivityScoped
@ContributesAndroidInjector(modules = { UserModule.class})
    abstract AActivity contributesYourActivityInjector();
}
  • 上面@ContributesAndroidInjector 标记,自动实现了DaggerXXXComponent 注入worker,内部实现了inject(XXXActviity instance)
    三要素中确定了 “原型Owner”和DaggerComponent 装配工人。

至于原型provider 提供者,可以通过构造方法用@inject修饰提供。或者为ContributesAndroidInjector 指定modules,去指定module寻找provider

@ContributesAndroidInjector(modules = { UserModule.class})

六 android-dagger actvity注入简化流程

1、MyApp 实现HasActivityInjector接口,提供activityInjector


class MyApp : Application(), HasActivityInjector  {


    @Inject
    lateinit var dispatchingActivityAndroidInjector: DispatchingAndroidInjector

  

    @Inject
    @JvmField
    var theAppApi: AppApi? = null

    override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.builder().build().injectApp(this)

        Log.d("feifei","验证application的注入情况 - dispatchingAndroidInjector.size:"+dispatchingActivityAndroidInjector
                +"\n,dispatchingFragmentAndroidInjector:"+dispatchingFragmentAndroidInjector
                +"\n,theAppApi:"+theAppApi
        )
    }

    override fun activityInjector(): AndroidInjector? {
        return dispatchingActivityAndroidInjector
    }

  
}

2 定义AppModule 和AppComponent,并在MyApp的onCreate()中调用注入方法

AppModule.java

@Module
public abstract class AppModule {
    @Binds
    abstract TheService getApiService(AppApi appApi);
}

AppComponent.java

@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class,
    }
)
public interface AppComponent {

    public void injectApp(MyApp app);

    @Component.Builder
    interface Builder{
        AppComponent build();
    }
}

MyApp.kt

 override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.builder().build().injectApp(this)

        Log.d("feifei","验证application的注入情况 - dispatchingAndroidInjector.size:"+dispatchingActivityAndroidInjector
                +"\n,dispatchingFragmentAndroidInjector:"+dispatchingFragmentAndroidInjector
                +"\n,theAppApi:"+theAppApi
        )
    }

至此可以完成MyApp 中dispatchingActivityAndroidInjector的注入,只不过没有 Map, Provider>>的数据源,注入的是空map的
DispatchingAndroidInjector

class MyApp : Application(), HasActivityInjector , HasSupportFragmentInjector {


    @Inject
    lateinit var dispatchingActivityAndroidInjector: DispatchingAndroidInjector

    
}
public final class DispatchingAndroidInjector implements AndroidInjector {

private final Map, Provider>>
      injectorFactories;
       @Inject
  DispatchingAndroidInjector(
      Map, Provider>> injectorFactories) {
    this.injectorFactories = injectorFactories;
  }
 }

3、定义ActivithModule,用ContributesAndroidInjector ,将所有的需要注入的Activity进行注册。

此时会为注入的activity提供provider,同时会生成一个Map的map,此map可以作为provider为,辅助构造MyApp中的
dispatchingActivityAndroidInjector
ActivityModule.java

@Module
abstract class ActivityModule {
    //
    //
    /**
     * 1、需要通过AndroidInjection.inject()进行注入的所有activity,都集中写到ActivityModule中,如下所示
     * 2、@ContributesAndroidInjector 标注会自动生成DaggerXXXComponent(如DaggerMainActivityComponent),其继承自AndroidInjector(如AndroidInjector)
     * 并实现了  void inject(T instance);方法(如,void inject(MainActivity instance))。
     * 至此已经自动实现了dagger注入三要素中的 "组装工人worker"和 owner(如MainActivity)
     * 如果自动生成的DaggerXXXComponent 中需要额外的provider才能够完成依赖注入,那可以将包含provider的module 添加给DaggerXXXComponent, 方法如下(利用modules =):
     * @ContributesAndroidInjector(modules = [ThirdModule::class])标签
      */

    @ContributesAndroidInjector
    abstract fun contributeMain():MainActivity

    @ContributesAndroidInjector
    abstract fun controbuteSecond(): SecondActivity

    @ContributesAndroidInjector(modules = [ThirdModule::class])
    abstract fun controbuteThird(): ThirdActivity

    @ContributesAndroidInjector
    abstract fun controbuteFour(): FourActivity

}

4、在BaseActivity中调用 AndroidInjection.inject(this),具体触发Activitry的注入操作

open class BaseActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        AndroidInjection.inject(this)
    }
}

需要注意,

  • 所有需要注入的Activity 需要继承BaseActivity类
  • 所有需要注入的Activity 都需要在ActivityModule中进行注册

5、在Activity中 用@inject 标记需要注入的对象,并提供该对象的provider即可完成注入

public class SecondActivity extends BaseActivity {

    @Inject
    User mUser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Log.d("feifei","mUser.name:"+mUser.getName());
    }
}
public class User {
    private String name;
    @Inject
    public User(){
        this.name = "小美";
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

备注:

1、Fragment 和Service的注入流程与此类似

2、github示例代码:

https://github.com/feifei-123/TestDragger2

七、参考文章:

  • https://www.jianshu.com/p/26d9f99ea3bb
  • 轻松理解AndroidInjector(dagger-android)三部曲
    https://juejin.im/post/5cc72061e51d456e6154b4bc

你可能感兴趣的:(Dagger2使用)