我正在参与「启航计划」

上一篇文章的方便进口:写文章 – 运用Hilt完结依靠注入,让你的安卓代码层次有几层楼那么高(三) – ()

辅佐注入

如果通过看前面的文章学会了Hilt的基础运用,那么恭喜你,你基本现已能够在项目中展开运用Hilt结构为你的项目提供自动注入功能了,可是有一些场景你或许会感到疑问,回顾之前的注入,你会发现一个问题:当运用Hilt构建一个目标的时分,在界说目标的时分,就要求一切参数现已被确认,可是实践场景中,咱们有许多参数是无法在界说目标的阶段就被确认的,一些参数需求在项目运行时才能被确认,例如网络恳求的成果等,这些动态的参数让咱们无法运用Hilt为咱们注入,至少目前还不行。

为了处理这些动态参数导致的问题,dagger2(即Hilt的底层结构)提供了一种处理问题的方案:辅佐注入

辅佐注入是一种依靠注入 (DI) 模式,用于构造一个目标,其间一些参数或许由 DI 结构提供,而其他参数必须在创立时由用户传入(也称为“辅佐”)。 工厂一般担任组合一切参数并创立目标。

依然是废话不多说环节,咱们运用详细的事例来解说怎么运用辅佐注入


data class Wheel(
    val name:String
)
data class Engine(
    val name:String
)
class Car(
    val wheel:Wheel,
    val engine:Engine,
    val number:Int
)

假定咱们有轮子、引擎和轿车三个实体类,其间轿车是由轮子和引擎组成的,咱们希望创立一个工厂,自动为咱们生成某个类型的轿车,因此轮子和引擎的构建办法是固定的,可是轿车的编号每个轿车是不同的。

依照之前的文档,咱们编写Module类,可是咱们会发现,咱们无法在界说provides办法阶段就界说好number。

@InstallIn(SingletonComponent::class)
@Module
object JiLiCarModule{
    @Singleton
    @Provides
    fun provideJiLiWheel():Wheel{
        return Wheel("吉祥牌车轮")
    }
    @Singleton
    @Provides
    fun provideJiLiEngine():Engine{
        return Engine("吉祥牌引擎")
    }
    @Provides
    fun provideJiLiCar(
        wheel: Wheel,
        engine: Engine
    ):Car{
        return Car(
            wheel = wheel,
            engine = engine,
            //出问题的部分,咱们无法清晰这个编号
            number = ???
        )
    }
}

或许某些情况下,咱们确实能在界说provides办法的时分就清晰number的生成办法(例如随机数的业务场景),可是咱们要评论的是在界说provides办法阶段无法清晰参数的情况,因此咱们需求dagger提供的辅佐注入来协助咱们完结这种场景下的Hilt注入。

动手实战

一、为轿车实体类增加@AssistedInject注解,一起为动态传入的参数增加@Assisted注解,这儿是number。

class Car @AssistedInject constructor(
    val wheel:Wheel,
    val engine:Engine,
    @Assisted
    val number:Int
)

二、构建工厂类,运用@AssistedFactory注解表明这是一个辅佐注入工厂类,一起编写需求注入的实体类的构建办法,办法只需求动态传入的参数,在这儿指的是number

@AssistedFactory
interface JiLiCarFactory{
    fun createJiLiCar(
        number:Int
    ):Car
}

三、注入工厂类,这儿和之前直接注入目标运用办法基本是一致的,差异只要一个,这儿注入的是工厂

@AndroidEntryPoint
class YouFragment : Fragment() {
    //注入工厂类
    @Inject
    private lateinit var jiLiCarFactory: JiLiCarFactory
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //运用工厂类,传入动态参数构建详细的目标
        val jiLiCar: Car =jiLiCarFactory.createJiLiCar(114514)
    }
}

四、处理相同类型参数注入问题

当你有多个相同类型的参数的时分,Hilt会不知道怎么注入,例如咱们的实体类是这样的情况:

class Car @AssistedInject constructor(
    val wheel:Wheel,
    val engine:Engine,
    @Assisted
    val number:Int,
    @Assisted
    val number2:Int
)

这儿呈现了两个相同类型(Int)的参数,因此咱们需求区别开来,这儿运用注解@Assisted的参数来区别,改造为如下:

class Car @AssistedInject constructor(
    val wheel:Wheel,
    val engine:Engine,
    @Assisted("number")
    val number:Int,
    @Assisted("number2")
    val number2:Int
)

一起别忘了为工厂的办法也增加对应的注解,否则Hilt相同无法知道怎么映射对应的参数

@AssistedFactory
interface JiLiCarFactory{
    fun createJiLiCar(
        @Assisted("number") number:Int,
        @Assisted("number2") number2:Int
    ):Car
}

工厂类用法和原来的保持一致,仅仅多加了参数

val jiLiCar=jiLiCarFactory.createJiLiCar(114514,1111)

总结

好的,关于Hilt的系列就到此结束了,笔者写这系列的初衷是协助那些刚刚运用Hilt的新手快速入门并动手运用Hilt,并没有做太深化的剖析(笔者的程度也没有到那个层次,就不布鼓雷门了),一起也为很久没有更新文章抱愧,近期会恢复更新频率,一起也会谈谈compose相关的话题,敬请期待。