Dagger2源码

dagger2的GitHub地址

优秀的小白入门博客

大神的dagger2详解博客

本文Demo

只有Inject的模式
  • activity(Inject成员变量,告诉dagger拿到对象之后赋值给它)

      @Inject
      lateinit var person: Person
      
      override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)
       DaggerMainComponent.builder().build().injectMain(this)
      }
    
  • Component

      @Component
      interface MainComponent{
          fun injectMain(activity: MainActivity)
      }
    
  • 需要inject拿到的对象(告诉dagger我要拿到这个类的对象)

      class Person @Inject constructor() {
      }
    

@Inject有两项职责:

  • 注解构造函数:通过标记构造函数,告诉Dagger 2可以创建该类的实例(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖关系。
  • 注解依赖变量:通过标记依赖变量,Dagger2提供依赖关系,注入变量

创建好这三个类要先build一下,然后会自动生成对应的Component类。
先看看生成的DaggerMainComponent类源码

public final class DaggerMainComponent implements MainComponent {
  private DaggerMainComponent(Builder builder) {}

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

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

  @Override
  public void injectMain(MainActivity activity) {
    injectMainActivity(activity);
  }

  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectPerson(instance, new Person());
    return instance;
  }

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

    public MainComponent build() {
      return new DaggerMainComponent(this);
    }
  }
}

可以看到DaggerMainComponent.builder().build()和DaggerMainComponent.create()效果是一样的。

编译之后生成了对应的Injector类

person对象是在injectMainActivity方法中new出来的。

MainActivity_MembersInjector.injectPerson(instance, new Person());

再看看Injector的源码

public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final Provider<Person> personProvider;

  public MainActivity_MembersInjector(Provider<Person> personProvider) {
    this.personProvider = personProvider;
  }

  public static MembersInjector<MainActivity> create(Provider<Person> personProvider) {
    return new MainActivity_MembersInjector(personProvider);
  }

  @Override
  public void injectMembers(MainActivity instance) {
    injectPerson(instance, personProvider.get());
  }

  public static void injectPerson(MainActivity instance, Person person) {
    instance.person = person;
  }
}

然后直接赋值到activity类的成员变量中

public static void injectPerson(MainActivity instance, Person person) {
    instance.person = person;
  }
Inject、Module、Provide完整模式

有时候只用Inject不能获取到对象了,比如person是一个第三方库类,这样你就不能直接Inject它的构造方法了,这个时候就需要module和provide

  • activity

      class MainActivity : AppCompatActivity() {
          @Inject
          lateinit var person: Person
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_main)
              DaggerMainComponent.builder().module(Module()).build().injectMain(this)
              Log.d("eee=person", "" + person.hashCode())
          }
      }
    
  • Component(Module可以多个,逗号隔开)

      @Component(modules = [Module::class])
      interface MainComponent{
          fun injectMain(activity: MainActivity)
      }
    
  • Module

      @Module
      class Module {
          @Provides
          fun providePerson():Person{
              return Person()
          }
      }
    
  • person

      class Person {}
    

可以看到这个示例代码中其实就是在module中创建好了对象,最后传到activity中的。

DaggerMainComponent中的关键代码是injectMain

  @Override
  public void injectMain(MainActivity activity) {
    injectMainActivity(activity);
  }

  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectPerson(
        instance, Module_ProvidePersonFactory.proxyProvidePerson(module));
    return instance;
  }

调用Module_ProvidePersonFactory的proxyProvidePerson,就是拿module中你创建的那个对象

  public static Person proxyProvidePerson(Module instance) {
    return Preconditions.checkNotNull(
        instance.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
  }

MainActivity_MembersInjector.injectPerson就是最后的赋值操作了

  public static void injectPerson(MainActivity instance, Person person) {
    instance.person = person;
  }

当person有多个构造函数并Inject了多个构造的时候,provide不知道要提供哪个构造方法,将造成“依赖迷失

IntoSet、IntoMap
  • activity

      class MainActivity : AppCompatActivity() {
      
          @Inject
          lateinit var bananaSet:Set<BananaBean>
          @Inject
          lateinit var setBananaBean: SetBananaBean
      
          @Inject
          lateinit var bananaByString:Map<String,BananaBean>
          @Inject
          lateinit var bananaByClass:Map<Class<*>,BananaBean>
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_main)
      
              val build = DaggerMainComponent.builder().build()
              build.injectMain(this)
      
              val banana = build.setBanana()
              Log.d("eee=banana1",banana.toString())
              Log.d("eee=banana2",banana.toString())
              Log.d("eee=banana3",banana.toString())
              Log.d("eee=bananaSet",bananaSet.toString())
              Log.d("eee=setBananaBean",setBananaBean.toString())
      
              Log.d("eee=component string",build.bananaByString().toString())
              Log.d("eee=component class",build.bananaByClass().toString())
              Log.d("eee=Inject string",bananaByString.toString())
              Log.d("eee=Inject class",bananaByClass.toString())
          }
      }
    
  • module

      @Module
      class DrinkModule {
          @Provides
          @IntoSet
          fun providerBanana(): BananaBean {
              return BananaBean("特朗普香蕉")
          }
      }
      
      @Module
      class FruitModule {
          @Provides
          @IntoSet
          fun providerBanana(): BananaBean {
              return BananaBean("特朗普--香蕉")
          }
      }
      
      @Module
      class MultiModule {
          @Provides
          @ElementsIntoSet
          fun providerBananaSet(): Set<BananaBean> {
              var set = HashSet<BananaBean>()
              set.add(BananaBean("布什香蕉"))
              set.add(BananaBean("约翰逊香蕉"))
              return set
          }
      
          @Provides
          @IntoMap
          @StringKey("a")
          fun providerBananaMap(): BananaBean {
              return BananaBean("a apple")
          }
      
          @Provides
          @IntoMap
          @ClassKey(Person::class)
          fun providerClassMap(): BananaBean {
              return BananaBean("class apple")
          }
      
      }
    
  • bean(kotlin中不要像Java那样单独写个方法写构造,否则inject无效)

      class SetBananaBean @Inject constructor(val set:Set<BananaBean>) {
      
          override fun toString(): String {
              return super.toString()
          }
      }
      
      class BananaBean(val s:String) {
      
          override fun toString(): String {
              return s
          }
      }
    
  • Component

      @Component(modules = [Module::class,FruitModule::class,DrinkModule::class,MultiModule::class])
      interface MainComponent{
          fun injectMain(activity: MainActivity)
          fun setBanana():Set<BananaBean>
          fun bananaByString():Map<String,BananaBean>
          fun bananaByClass():Map<Class<*>,BananaBean>
      }
    
  • 运行结果

       D/eee=banana1: [特朗普香蕉, 约翰逊香蕉, 特朗普--香蕉, 布什香蕉]
       D/eee=banana2: [特朗普香蕉, 约翰逊香蕉, 特朗普--香蕉, 布什香蕉]
       D/eee=banana3: [特朗普香蕉, 约翰逊香蕉, 特朗普--香蕉, 布什香蕉]
       D/eee=bananaSet: [布什香蕉, 约翰逊香蕉, 特朗普香蕉, 特朗普--香蕉]
       D/eee=setBananaBean: com.example.admin.baladagger2.test1.SetBananaBean@676e725
       D/eee=component string: {a=a apple}
       D/eee=component class: {class com.example.admin.baladagger2.test1.Person=class apple}
       D/eee=Inject string: {a=a apple}
       D/eee=Inject class: {class com.example.admin.baladagger2.test1.Person=class apple}
    

查看源码知道关键代码在DaggerMainComponent类,继承MainComponent重写setBanana方法

@Override
  public Set<BananaBean> setBanana() {
    return SetBuilder.<BananaBean>newSetBuilder(3)
        .add(FruitModule_ProviderBananaFactory.proxyProviderBanana(fruitModule))
        .add(DrinkModule_ProviderBananaFactory.proxyProviderBanana(drinkModule))
        .addAll(MultiModule_ProviderBananaSetFactory.proxyProviderBananaSet(multiModule))
        .build();
  }

 

public MainComponent build() {
  if (fruitModule == null) {
    this.fruitModule = new FruitModule();
  }
  if (drinkModule == null) {
    this.drinkModule = new DrinkModule();
  }
  if (multiModule == null) {
    this.multiModule = new MultiModule();
  }
  return new DaggerMainComponent(this);
}

@Override
  public void injectMain(MainActivity activity) {
    injectMainActivity(activity);
  }
  
private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectBananaSet(instance, setBanana());
    MainActivity_MembersInjector.injectSetBananaBean(instance, getSetBananaBean());
    MainActivity_MembersInjector.injectBananaByString(instance, bananaByString());
    MainActivity_MembersInjector.injectBananaByClass(instance, bananaByClass());
    return instance;
}

多个component不能同时inject到一个类中

例如:

A component中有  fun inject(Bala:Activity)
B component中也有  fun inject(Bala:Activity)
dependencies

使用场景:你需要的对象中需要其他的对象,例如“车”需要有”颜色“

  • Car

      class Car(val brand:String,val color:VehicleColor) {
          fun go(){
              Log.d("eee=car",brand+"go --color is"+color.color)
          }
      }
    
  • CarComponent

      @Component(modules = CarModule.class, dependencies = ColorComponent.class)
      public interface CarComponent {
          void inject(CarActivity activity);
      }
    
  • CarModule

      @Module
      public class CarModule {
          @Provides
          Car provideCar(VehicleColor color){
              return new Car("兰博基尼",color);
          }
      }
    
  • ColorComponent

      @Component(modules = ColorModule.class)
      public interface ColorComponent {
          VehicleColor carColor();
      }
    
  • ColorModule

      @Module
      public class ColorModule {
          @Provides
          VehicleColor provideCarColor(){
              return new VehicleColor("红色");
          }
      
      }
    
  • Component2

      @Component(modules = [Module2::class],dependencies = [MainComponent::class])
      interface Component2 {
          fun inject(activity:Test2)
      }
    
  • Module2

      @Module
      class Module2 {
          @Provides
          fun provideTest2():Person2{
              return Person2()
          }
      }
    
  • VehicleColor

      class VehicleColor(val color:String) 
    
  • CarActivity

      class CarActivity: AppCompatActivity() {
          @Inject
          lateinit var car: Car
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              DaggerCarComponent.builder().colorComponent(DaggerColorComponent.create()).build().inject(this)
              car.go()
          }
      }
    
  • 运行结果

      D/eee=car: 兰博基尼go --color is红色
    
  • 分析

  1. 看了下Car这个类,需要color这个字符串,是怎么传进去的
  2. 没有直接操作CarModule,怎么创建出的car对象

首先直接看inject这个方法做了啥?在DaggerCarComponent中可以看到

@Override
public void inject(CarActivity activity) {
    injectCarActivity(activity);
}

private CarActivity injectCarActivity(CarActivity instance) {
    CarActivity_MembersInjector.injectCar(instance, getCar());
    return instance;
}
  
private Car getCar() {
    return CarModule_ProvideCarFactory.proxyProvideCar(
        carModule,
        Preconditions.checkNotNull(
            colorComponent.carColor(), "Cannot return null from a non-@Nullable component method"));
}

getCar方法中拿到的就是car的对象,里面传入carModule和colorComponent,module中有car的对象的方法,component中有car所需要的颜色。然后在CarModule_ProvideCarFactory中创建中car对象

  public static Car proxyProvideCar(CarModule instance, VehicleColor color) {
    return Preconditions.checkNotNull(
        instance.provideCar(color), "Cannot return null from a non-@Nullable @Provides method");
  }

car就是这样创建和传递的。现在的问题是carModule和colorComponent是怎么出来的。在DaggerCarComponent的Builder类中可以看到

  public static final class Builder {
    private CarModule carModule;

    private ColorComponent colorComponent;

    private Builder() {}

    public CarComponent build() {
      if (carModule == null) {
        this.carModule = new CarModule();
      }
      if (colorComponent == null) {
        throw new IllegalStateException(ColorComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerCarComponent(this);
    }

    public Builder carModule(CarModule carModule) {
      this.carModule = Preconditions.checkNotNull(carModule);
      return this;
    }

    public Builder colorComponent(ColorComponent colorComponent) {
      this.colorComponent = Preconditions.checkNotNull(colorComponent);
      return this;
    }
  }

虽然CarModule没有直接操作,但是build方法中判断为空的时候会自动new出来,然后赋值给DaggerCarComponent的成员变量carModule。colorComponent是你自己传进去的(通过DaggerColorComponent.create())

public final class DaggerColorComponent implements ColorComponent {
  private ColorModule colorModule;

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

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

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

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

  @Override
  public VehicleColor carColor() {
    return ColorModule_ProvideCarColorFactory.proxyProvideCarColor(colorModule);
  }

  public static final class Builder {
    private ColorModule colorModule;

    private Builder() {}

    public ColorComponent build() {
      if (colorModule == null) {
        this.colorModule = new ColorModule();
      }
      return new DaggerColorComponent(this);
    }

    public Builder colorModule(ColorModule colorModule) {
      this.colorModule = Preconditions.checkNotNull(colorModule);
      return this;
    }
  }
}

关键代码来了,在build方法中可以看到,里面new了一个ColorModule出来,ColorModule中就提供了获取VehicleColor也就是颜色对象的方法。然后把ColorModule对象赋值给Builder类的成员变量,再new一个DaggerColorComponent(this),这个this就是保存了ColorModule对象的Builder。然后在DaggerColorComponent里面又把Builder中colorModule拿出来保存在自己的成员变量中,此时DaggerColorComponent也就拿到了颜色。

最后还是一样的套路,拿到了car构造所需要的参数(在DaggerColorComponent中),拿到了可以创建car的方法(在carModule中),然后再用inject赋值

Subcomponent
  • Bike

      class Bike(val color: String) {
          fun go(){
              Log.d("eee=bike","bike is running -- color is "+color)
          }
      }
    
  • BikeComponent

      @Subcomponent(modules = BikeModule.class)
      public interface BikeComponent {
      
          Bike supplyBike();
      
          @Subcomponent.Builder
          interface Builder{
              Builder bikeModule(BikeModule module);
      
              BikeComponent build();
          }
      }
    
  • BikeModule

      @Module
      public class BikeModule {
          @Provides
          Bike provideCar(){
              return new Bike("  black ");
          }
      }
    
  • Brand

      class Brand(val name:String) {
          override fun toString(): String {
              return "Brand{  $name }"
          }
      }
    
  • BrandComponent

      @Component(modules =[ BrandModule::class])
      interface BrandComponent {
          fun inject(activity: BikeActivity)
      
          fun supplyBikeComponentBuild():BikeComponent.Builder
      }
    
  • BrandModule

      @Module(subcomponents = [BikeComponent::class])
      class BrandModule {
          @Provides
          fun provideBrand(): Brand {
              return Brand("林肯加长版")
          }
      }
    
  • BikeActivity

      class BikeActivity: AppCompatActivity() {
          @Inject
          lateinit var brand: Brand
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
      
      
              val brandComponent = DaggerBrandComponent.builder().build()
              brandComponent.inject(this)
      
              val supplyBike = brandComponent.supplyBikeComponentBuild().build().supplyBike()
              supplyBike.go()
              Log.d("eee=brand",brand.toString())
      
          }
      }
    
  • 运行结果

      D/eee=bike: bike is running -- color is   black 
      D/eee=brand: Brand{  林肯加长版 }
    
  • 源码都是类似的,没有分析的意义

https://www.jianshu.com/p/5fd066bf28fa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值