Android Koin2 基本使用那件事

首先什麼是KOIN?

適用於 Kotlin 開發人員的實用輕量級依賴注入框架。 用純 Kotlin 編寫,僅使用功能分辨率:無代理,無代碼生成,無反射。java

PS:KOIN 支持 Kotlin 和 Javaandroid

Koin 怎麼配置?

本文主要講解 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 怎麼使用?

Koin 入門使用至關容易,學會下面幾個關鍵詞就 OK 了,跟着來看看哦~

factory

今天 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())
    }
}
複製代碼

Activity 有了 Girl

看臉都是一我的啊!怎麼知道每次都是個新 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胞胎...

single

如今都什麼時代了,不能給它享受多個 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)
    }
}
複製代碼

Activity 的2個妹子

scope

scope 是個什麼東西呢?我理解是使用範圍,相似於生命週期,咱們能夠控制它的存活範圍。 來個其餘的栗子換個口味,先奉上效果圖:

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)
    }
複製代碼

描述下流程:

  1. 在 Scope1Activity 建立了 scope1 設置值,而且綁定(bindScope)了範圍。
  2. 跳轉到 Scope2Activity 先顯示原有值,修改後返回。因爲 Scope1Activity 沒有銷燬,因此在 onResume 顯示了新值。
  3. 返回 MainActivity ,因爲 scope 特性,此時已經獲取不到相應的值了。

Demo 地址: github.com/joker-fu/sa…

相關文章
相關標籤/搜索