依赖注入 – Koin 使用入门

写在前面

内容学习了郭霖的 Hilt 文章:Jetpack新成员,一篇文章带你玩转Hilt和依托注入

预览

1. Application DSL

KoinApplication 装备 Koin 注入的进口,有一下 API 可运用:

  1. koinApplication { } :创立一个 Koin 容器。
  2. startKoin { } :创立一个 KAPPoin 容器并将之注册到 GlobalContext 中,如此能够运用 GlobalContext 的 API 。
  3. logger( )接口类型 :挑选运用什么 Log 方法,Koin 供给了 3 种默许 Logger ,分别是 AndroidLoggerPrintapproachLoggerEmptyLogger ,它们都继接口卡承自抽象类 Logger ,如不装备默许运用 EmptyLogger ,即不打印。
  4. modules( ) :装备 Koin 模块并将之注入到 Koin 容器。
  5. properties() :运用 HashMap 注入特色,供全局查询修正。
  6. fileProperties( ) :运用给定 properties 文件注入特色,文javascript件需求放在 src/main/resources 目录下。
  7. environmentPropeappearrties( ) :注入体系、环境特色,经过 java.lang.System 注入。

2. Module DSL

  1. module { // module content } :创立一个 Koin 模块。android是什么手机牌子
  2. factory { //definition } :创立注approach入类的实例。
  3. single { //definition } :与android手机 factory 功用一起,只android下载安装不过创立的是单例。
  4. get() :经过解析组件依托,注入类实例。
  5. inject() :与 get() 功用一起,都是供给类注入,但 injec接口自动化t 是懒加载。
  6. b接口文档ind() :为注入类添加类型绑定,因为默许注入类只能对应一个类型。
  7. binds() :功用与上述 bind() 一起,一次性供给多个类型绑定。
  8. scope { // scope group } :为下述 scoped 界说一个合理的组,效果是控制注入类的生命周期。
  9. scoped { //definition }java面试题 :与上述 scope 协作APP运用,界说内放注入类的实例,标明只在 sandroid的drawable类cope 的范围内存在。
  10. named() :假定遇到相同类型需求两个或以上的注入,能够经过这个函数给注入进行命名,然后在注入处只需指定好称号即可获取正确的注入。

场景

1. 简略注入

  • 首要封装一下常用的 API ,接Android下来都会appreciate用到这些封装 API :

    inline fun <reified T :java面试题 Any> get(
    qualifier: Qjavaeeualifier? = null,
    noinline paramapp下载eterandroid是什么手机牌子s: ParametersDefinition? = null
    ): T {
    return GlobalContext.get().get<T>(qualifier, pa接口测验rameters)
    }
    inline fun <reiandroid平板电脑价格fied T : Any> inject(
    qualifier: Qualifier? = null,
    mode: LazyThre接口卡adSafetyMode = KoinPlatformTools.接口类型defaultLazandroid体系yMode(),
    noinline parameters: ParametersDefiniapplicationtion? = null
    ): Lazy<T> {
    return GlobalContext.get().inject(qualifieapplicationr, mode, parameters)
    }android/yunos
    

    这儿首要针对 GlobalContext.g接口测验et() 进行了封接口类型装,否则接口卡在事务代接口码中免不了需求写多一些样板代码。

  • 接下来装备一下注入信息,例如需求一辆车需求引擎:

    class Car
    val module = modules {
    factory { Car(android手机) }
    }
    class App : Application() {
    override fun onCreate() {
    super.onCreate()
    startKoin {
    modules(module)
    }
    }
    }
    
  • 然后就能够在调用处进行注入了:

    private val car = get<Car>()
    // or
    private val car by inject<Car>()
    

2. 带参数注入

  • Car 注入一个司机:

    class Driver
    class Car(val driver: DJavariver)
    vajava环境变量装备l module = moduleappetite {
    factory { params -> Car(params.get()) }
    // or
    fact接口和抽象类的差异ory { (drivjava语言er: Driver) -&gtapproach; Car(driver) }
    }
    

    在配approach备时我们运用到了Definition<T> ,这是 factory()single() 函数里界说的,它的原型是 Scope.(JavaParametersHolderappreciate) -> T ,我们能够经过 ParametersHolder 取出我们需求的参数进行创立目标,假定运用解构声明则参数最多只接受 5 个,超出无法运接口和抽象类的差异用解构声明,看代码:

    val module = modulandroid下载安装e {
    factory { (p1: Byte, p2: Short, p3: Inappstoret, p4: Long, p5: String) ->
    Obj(p1,java怎么读 p2, p3, p4, p5)
    }
    // 超出 5 个后手动调用 params 获取
    factory { pjavascriptarams ->
    Obj(params[app是什么意思0], params[1], params[2], params[3], params[4], params[5])
    }
    }
    private val obj = get<Obj> {
    parametersOf(
    1, 2, 3, 4L, "", //...
    )
    }
    

    注入时运用到了 ParametersDefinition ,这是 get()injejava模拟器ct() 函数里界说的,它的原型是 () -> ParametersHolder ,意味着需求回来一个 Parametersjava怎么读Holdeandroid下载r 给 Koin ,经过 parametersOf()android平板电脑价格 函数传android下载入参数,支撑可变参数。

3. 接口注入

  • 给车注入引擎:

    interfa接口自动化ce Engine
    class GasEngine
    class ElectricEngineapple
    val module = module {
    // 绑定为 GasEngine 类型
    factory { GasEngine() }
    // 绑定为 ElectricEngine 类型
    factory { ElectricEngine() }
    }
    class Car {
    private val gasEngine = get<GasEngine>()
    priandroid什么意思vate val electricEngine = get<接口卡ElectricEngine>()
    }
    

    这样能够结束接口的注入,但存在问题,默许情况下配补白入时只能绑定一个类型,即上述java初学代码各自绑定了 GasEngineElectricEngine ,因此在注入时只能明晰运用装备时绑定的类型,假定运用 get<Engiandroid下载安装ne>() 会报找不到界说失常。

    那假定想要经过 Engine 类型来获取注入该怎么做呢?

    // 第一种方法是在装备时明晰类型:
    factory<Engine&gappetitetandroid体系; { GasEngine() }
    // or
    factory { GasEngine asjava难学吗 Engine }
    // 第二种方法是运用 `bind()` 中缀函数:
    facappetitetory { Ga接口测验sEngine() } bind Engine::class
    

    bind() 函数需求传入想一起绑定的 KClass 类型,假定有多个类型需求一起绑定能够运用 binds() 函数传入一个类型 List 。

    当装备时运用了多类型绑定后,在界说注入时就能够依据想要的类型来进行注入了,但仍需求留心,一java难学吗个类型最多只能有一个装备,新的注入装备会掩盖旧装备(V2 版别中 override 默许关闭需求手动打开,V3 版别默许打开,可手动关闭),下面用比方来阐明:

    val module = module {
    factory { GasEngine() } bind Engine::class
    factory { ElectricEngine() } bind Engine::class
    }
    private val gasEngine = get<Engine&gjava环境变量装备t;()
    private val electricEngine = get<ElectricEngine>()
    

    运转后能够发现,无论是 gasappreciateEngine 还是 eleappointmentctrictEngine ,都会注入了 ElectricEngine ,因为在第二行装备时一起绑定了 Engine 类型,导致上一行的装备被掩盖,假定去除第二行装备的 bind Engine::class 即康复正常。那假定的确需求注入多个同类型该怎么办呢?下面会说到。

4. 相同类型注入

直接上代码:

val module = module {
factory(named("ga接口测验s")) { GasEngine() } bind Engine::class
factory(named("electric")) { ElectricEngine() } bind Engine::class
}
private var gasEngine = get<Engine>(named("gas"))
private var electricEngine = get<Engine>(named("electric"))

在装备与注入时均运用到了 Qualifier 约束符,factory()single() 函数都有供给形参,经过 named()appreciate 函数获取到 Qualifier 并传入即可获取需求的效果。

named() 支撑 3 种运用方法:

  1. named<KClass>() :经过泛型进行约束
  2. named(String) :经过字符串进行约束
  3. named(Enum) :经过枚举进行约束

named() 效果相同的还有 qualifier()_q() ,它们仅仅名字的差异,所以我也搞不明白为啥供给两个剩余 API 。

5. 第三方类注入

用法较前面没有不同,javascript略~

6. 泛型的处理

假定事务中不想重复创立容器类,需求创立后持续运用,可android手机以这么写:

val mojava模拟器dule = modul接口的界说e {
single(接口和抽象类的差异named("Ints")) { ArrayList<Inandroid下载t>() }
single(named("Strings")) { ArrayList&landroid是什么手机牌子t;String>() }
}

有必要运用 Qualif接口和抽象类的差异ier 进行约束。

7.APP Scope

效果域,能够赋接口自动化予我们运用的注入一段生命周期,用完手动关闭。

// 界说效果域内的装备
val module = module {
scope<String接口卡>{
scoped { Obj() }
// ...
}
}
class Test {
private val scope = GlobalContext.接口crc过错计数get().getOrCreateScope<String>("")
private val obj = scope.get<Obj>()
fun recycle() {
scope.close()
}
}

装备 Sc接口测验ope 时需求指定 scopeIdscoAndroidpeName(可运用 Qualifier 或泛型android平板电脑价格 ,运用注入时首要创立出 scope ,有一javaee下函数可供获取:

  1. createScope() :创立效果域接口自动化
  2. getScope :获取效果域,如不存在会报失常
  3. getOrCreateScope :获取效果域,如不存在会创立并回来

8. Properapp下载ties

可经过接口类型 Koin 增修正查暂时键值对,有一下 API :

  1. getProperty :依据 key 获取 valu接口测验e接口文档

  2. setPrandroid体系operty :设置键值对

  3. deleteProperty :删去键值对

9. 其他有用的 API

  1. loadModules :可加载装备模块
  2. unloa接口crc过错计数dModules :可卸载装备模块
  3. KoinComponent :完成这个接口获得 Koiandroid什么意思n KTX 功用
  4. Kandroid的drawable类oinScopeComponentKoinComponent 的子接口,完成此接口可运用 Koin Scope KTX 功用

发表评论

提供最优质的资源集合

立即查看 了解详情