適用於 Kotlin 開發人員的實用輕量級依賴注入框架。 用純 Kotlin 編寫,僅使用功能分辨率:無代理,無代碼生成,無反射。java
PS:KOIN 支持 Kotlin 和 Javaandroid
本文主要講解 Koin (2.0.1) 在AndroidX中的使用,因此直接添加 koin-android 依賴git
首先添加 Koin Android 基本依賴github
// Koin for Androidapp
implementation "org.koin:koin-android:$koin_version"框架
若是須要使用到 Scope(範圍) 控制,則依賴 koin-androidx-scopeide
// Koin AndroidX Scope featurespost
implementation "org.koin:koin-androidx-scope:$koin_version"this
若是項目中使用到ViewModel,那麼堅決果斷依賴 koin-androidx-viewmodelspa
// Koin AndroidX ViewModel features
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
既然使用Kotlin,擴展功能怎麼能少呢?添加 koin-androidx-ext
// Koin AndroidX Experimental features
implementation "org.koin:koin-androidx-ext:$koin_version"
Koin 入門使用至關容易,學會下面幾個關鍵詞就 OK 了,跟着來看看哦~
今天 Activity 須要一個 Girl(嗯~,多是幾個),那咱們就建立個依賴對象使用 Koin 注入給它,這時我須要每次都給它個新的(使用factory):
val girlModule = module {
factory {
Girl()
}
}
複製代碼
依賴對象有了,我得讓 Koin 知道,因此須要在咱們的 Application 初始化:
override fun onCreate() {
super.onCreate()
startKoin {
androidLogger(Level.DEBUG)
androidContext(this@App)
androidFileProperties()
modules(listOf(girlModule))
}
}
複製代碼
如今好像什麼都有,接下來當 Activity 須要時該怎麼給它呢?看 Activity 代碼:
// 註釋掉的是另外一種寫法
class Simple1Activity : AppCompatActivity() {
private val girl by inject<Girl>()
//private lateinit var girl: Girl
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sample1)
//girl = get()
ivImage.setImageResource(girl.getGirl())
}
}
複製代碼
看臉都是一我的啊!怎麼知道每次都是個新 Girl 呢?直接檢查 Girl 的身份證:
System.out: ---->com.joker.koin.model.Girl@a5b751b
System.out: ---->com.joker.koin.model.Girl@727e094
System.out: ---->com.joker.koin.model.Girl@e005b30
K,原來是3胞胎...
如今都什麼時代了,不能給它享受多個 Girl 啊,那就把 factory 換成 single,動手試試檢查 Girl 證件:
val girlModule = module {
single {
Girl()
}
}
複製代碼
System.out: ---->com.joker.koin.model.Girl@48146b8
System.out: ---->com.joker.koin.model.Girl@48146b8
System.out: ---->com.joker.koin.model.Girl@48146b8
如此簡單的咱們就實現了單例。什麼?同時要2個 Girl,還要不一樣類型且要是固定的。沒問題咱們有 Qualifier 和 Definition
val girlModule = module {
single(named("girl1")) { (type: String) ->
Girl().apply {
this.type = type
}
}
single(named("girl2")) { (type: String) ->
Girl().apply {
this.type = type
}
}
}
複製代碼
看看 Activity 怎麼樣了:
class Simple2Activity : AppCompatActivity() {
private val girl1 by inject<Girl>(named("girl1")) { parametersOf("可愛") }
private val girl2 by inject<Girl>(named("girl2")) { parametersOf("性感") }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sample1)
ivImage.setImageResource(girl1.getGirl())
ivImage.postDelayed({
ivImage.setImageResource(girl2.getGirl())
}, 3000)
}
}
複製代碼
scope 是個什麼東西呢?我理解是使用範圍,相似於生命週期,咱們能夠控制它的存活範圍。 來個其餘的栗子換個口味,先奉上效果圖:
val girlModule = module {
scope(named("scope")) {
scoped {
ScopeEntity()
}
}
}
複製代碼
scope 必須得指定 Qualifier,建立了 scope 依賴。接下來就是 createScope 和 bindScope,在這裏設置了默認值 "Scope1Activity":
class Scope1Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scope1)
//建立 scope 須要指定 id 和 qualifier,getScope 須要id
val scope1 = getKoin().createScope("scope1", named("scope"))
//默認綁定onDestory
bindScope(scope1)
scope1.get<ScopeEntity>().text = "Scope1Activity"
tvText.text = scope1.get<ScopeEntity>().text
btn.setOnClickListener {
startActivity(Intent(this, Scope2Activity::class.java))
}
}
override fun onResume() {
super.onResume()
tvText.text = getKoin().getScope("scope1").get<ScopeEntity>().text
}
}
複製代碼
在 Scope2Activity 使用 getScope 獲取並修改新值 "Scope2Activity":
class Scope2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scope1)
val scope1 = getKoin().getScope("scope1")
scope1.get<ScopeEntity>().text = "Scope2Activity"
tvText.text = scope1.get<ScopeEntity>().text
}
}
複製代碼
在 Scope1Activity 執行 onDestory 時,幫定在其中的 scope 就已經 close 了,這時再 getScope 將拋出異常:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
//驗證 scope銷燬 延時是爲了保證 Scope1Activity 已經執行 onDestory
scope.postDelayed({
scope.text = try {
getKoin().getScope("scope1").get<ScopeEntity>().text
} catch (e: Exception) {
"scope back"
}
}, 3000)
}
複製代碼
描述下流程:
Demo 地址: github.com/joker-fu/sa…