Dragger2中的继承 subcomponent

198 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情

image.png

我们在平时做一个项目的时候,可能不止一个模块,可能会有很多个library,总不能把所有library全部注入到一个component里面去吧。所以我们就需要将component拆成多个,拆成多个当然这几个是需要有一定的关系才能有关联。在dagger2里面提供两种方式一种依赖(dependencies)另外一种就是subcomponent。今天我们就先看看subcomponent的做法。

使用subcomponent这个是一个继承的关系。把一个component标记为一个subcomponent当然需要@Subcomponent这个关键字,subcomponent如下:

@Subcomponent(modules=[SubModuleExample::class])
interface SubComponentExample {
    @Subcomponent.Builder
    interface Builder{
        fun build():SubComponentExample
    }
    fun inject(mainActivity: MainActivity)
}

这个里面有一个必要的因素,把就是 @Subcomponent.Builder,这个必须要进行声明.在调用地方:

daggerExampleComponent.subComponentExample().build().inject(this)

当然上次我们讲了创建实例可以使用builder也可以使用factory,factory的写法如下:

@Subcomponent.Factory
interface Factory{
    fun  create():SubComponentExample
}

那在使用的地方就是:

daggerExampleComponent.subComponentExample().create().inject(this)

只是创建实例的方式不一样,其实都大同小异。

上面的SubModuleExample是subcomponent里面提供的provider

@Module
class SubModuleExample {
    @Provides
    fun providerTasla():Car{
        return Tasla()
    }
}

其实也很简单就是简单声明一个module。

那下面看最重要的部分,如果关联到parent component里面:

interface ExampleComponent {
   @Component.Builder
    interface Builder {
       @BindsInstance
        fun setContext(context: Context):Builder
        fun build(): ExampleComponent
    }
    fun subComponentExample():SubComponentExample.Factory
 
}

其实只需要在parent component里面添加一个返回subcomponent的实例就好了。当然这里根据subcomponent声明的创建方式返回,这里是使用factory,如果使用Builder那么就返回:SubComponentExample.Builder

我们现在是在subcomponent的module里面创建了一个car的实例,car是一个interface,实现类是tasla,如下:

interface Car {
    fun getCarName():String
}
class Tasla @Inject constructor():Car {
    override fun getCarName(): String {
       return "Tasla"
    }
}

我们把这个类在MainActivity中使用,但是这个是属于subcomponent里面的,所以我们需要把MainActivity注入到subComponent里面去,要不然注入就失败了,刚开始为这个问题困了好久,最后才发现:

fun inject(mainActivity: MainActivity)

在使用的地方:

val daggerExampleComponent = DaggerExampleComponent.builder().setContext(this.applicationContext).build()
daggerExampleComponent.subComponentExample().create().inject(this)

dagger初始化,以及subcomponent的初始化

@Inject
 lateinit var tasla: Car

如果Car这个类

Log.i("daggerExample","car name:${tasla.getCarName()}")

打印结果:

I/daggerExample: car name:Tasla

我们看看生成的类里面:

private MainActivity injectMainActivity(MainActivity instance) {
  ...
  SubModuleExample_ProviderTaslaFactory.providerTasla(subModuleExample));
  return instance;
}

这一段是给MainActivity注入的对象,是通过subModuleExample来提供

public SubComponentExample.Factory subComponentExample() {
  return new SubComponentExampleFactory(exampleComponentImpl);
}

这一段是创建subComponent的实例,从创建实例可以看出,它把parent的comoponent实例对象传入到了subcomponent里面,那意思就是它可以访问父类public提供的所有注入了。