Koin框架,适用于使用Kotlin开发 ,是一款轻量级的依赖注入框架,无代理,无代码生成,无反射。
相对于dagger 而言更加适合Kotlin语言。
官方网站
GitHub
用于创建KoinApplocation的实例配置
startKoin {
this.androidContext(this@App)//koin获取context
}
创建一个KoinApplication 可以在其中使用GlobalContext 的Api 一般用作全局初始化
描述要使用的Log 级别,默认使用EmptyLogger
要加载的模块列表
放置所有的properties 参数为HashMap
可以使用KoinComponent 获取到koin对象,获取放置的Value
将给定文件的属性加载到Koin
将属性从OS环境中加载到Koin
KoinApplication 可以通过koinApplication{} 和startKoin{} 两种方式创建这两种方式的区别:
/**
* Create a KoinApplication instance and help configure it
* @author Arnaud Giuliani
*/
fun koinApplication(appDeclaration: KoinAppDeclaration): KoinApplication {
val koinApplication = KoinApplication.create()
appDeclaration(koinApplication)
return koinApplication
}
//koinApplication{} 这种方式只创建KoinApplication
/**
* Start a Koin Application as StandAlone
*/
fun startKoin(appDeclaration: KoinAppDeclaration): KoinApplication {
val koinApplication = KoinApplication.create()
GlobalContext.start(koinApplication)
appDeclaration(koinApplication)
koinApplication.createEagerInstances()
return koinApplication
}
/**
* Start a Koin Application as StandAlone
*/
@JvmStatic
fun start(koinApplication: KoinApplication) {
if (app != null) {
throw KoinAppAlreadyStartedException("A Koin Application has already been started")
}
app = koinApplication
}
//startKoin{} 则执行了 GlobalContext.start(koinApplication)
/**
* KoinComponent interface marker to bring Koin extensions features
*
* @author Arnaud Giuliani
*/
interface KoinComponent {
/**
* Get the associated Koin instance
*/
fun getKoin(): Koin = GlobalContext.get().koin
}
看源码发现 koinApplication{} 还需要调用 GlobalContext.start(koinApplication) 才能使用
创建一个model,module 只是一个定义类型的逻辑空间,所以不同module 也可以使用get()
提供一个工厂(每次注入都会创建新的) Bean
创建一个单例的Bean 也可以通过不同的别名去声明不同一种类型的Bean
用于解决组件之间的依赖关系,也可以使用name ,scope,parameters
// Presenter <- Service
class Service()
class Controller(val view : View)
val myModule = module {
// declare Service as single instance
single { Service() }
// declare Controller as single instance, resolving View instance with get()
single { Controller(get()) }
}
//get() 方法使用获取了 声明的Service()
为给定的bean定义添加要绑定的类型
// Service interface
interface Service{
fun doSomething()
}
// Service Implementation
class ServiceImp() : Service{
fun doSomething() { ... }
}
val myModule = module {
// Will match types ServiceImp & Service
single { ServiceImp() } bind Service::class
}
// bind 方法 可以让ServiceImp 和 Service 绑定
这样你inject ServiceImp 也可以 inject Service
为给定的bean定义添加类型数组
为范围定义定义逻辑组
提供仅存在于scope内的bean定义
Koin 不允许同一名称的同一类型声明多次,你可以为同一种类型声明两个定义:
val myModule = module {
single(named(name = "default")) { ServiceImpl() }
single(named(name = "test")) { ServiceImpl() }
}
val service : Service by inject(name = "default")
也可以这样
val myModule = module {
single { ServiceImpl1() }
single(named(name = "test")) { ServiceImpl2() }
}
val service : Service by inject() //默认注入的是 ServiceImpl1
class Presenter(val view : View)
val myModule = module {
single{ (view : View) -> Presenter(view) }
}
//在single factory scope 中可以使用这种方式来注入参数
与已声明的类型不同,注入参数是通过解析inject传递的参数来注入
val presenter : Presenter by inject { parametersOf(view) }
//使用paramtersOf
声明一个类型或module 在什么时候创建(使用时 or 开始) false 使用时再创建,true startKoin 就创建
val myModule = module {
// 声明Service 类型在开始就创建
single(createAtStart=true) { TestServiceImp() }
}
val myModuleB = module(createAtStart=true) {
single{ TestServiceImp() }
}
Koin 不允许同一名称同一类型声明多次,当你需要声明多次时,你可以使用override
val helloModule = module {
single { "a" }
single(override = true) { "b" }
single(override = true) { "c"}
}
fun main(args: Array) {
startKoin {
modules(helloModule)
}
print(Test().str)//c
}
class Test:KoinComponent{
val str by inject ()
}
module {
single { ArrayList() }
single { ArrayList() }
}
/*Already existing definition or try to override an existing one: [type:Single,class:'java.util.ArrayList']*/
//这样会抛出异常
val helloModule = module {
single(named(name = "Ints")) { ArrayList() }
single(named(name = "Strings") ) { ArrayList() }
}
//这样就可以了
需要实现注入必须实现KoinComponent 接口
你可以使用get() & inject() 实现注入
//非懒加载
val str : String = get()
//懒加载,在用到的时候才注入
val str2:String by inject()