一、簡(jiǎn)介
KOIN - a pragmatic lightweight dependency injection framework for Kotlin
https://insert-koin.io/
二嗓违、集成
根據(jù)情況引入對(duì)應(yīng)的庫
Android
// Koin for Android
implementation "org.koin:koin-android:$koin_version"
// Koin Android Scope features
implementation "org.koin:koin-android-scope:$koin_version"
// Koin Android ViewModel features
implementation "org.koin:koin-android-viewmodel:$koin_version"
// Koin Android Experimental features
implementation "org.koin:koin-android-ext:$koin_version"
AndroidX
// Koin AndroidX Scope features
implementation "org.koin:koin-androidx-scope:$koin_version"
// Koin AndroidX ViewModel features
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
// Koin AndroidX Experimental features
implementation "org.koin:koin-androidx-ext:$koin_version"
三震捣、基本使用
1瘪弓、創(chuàng)建被注入組件
interface HelloRepository {
fun giveHello(): String
}
class HelloRepositoryImpl() : HelloRepository {
override fun giveHello() = "Hello Koin"
}
class MySimplePresenter(val repo: HelloRepository) {
fun sayHello() = "${repo.giveHello()} from $this"
}
2宰掉、創(chuàng)建Koin module
val appModule = module {
// HelloRepository 單例
single<HelloRepository> { HelloRepositoryImpl() }
// Simple Presenter Factory
factory { MySimplePresenter(get()) }
}
- module 類似dagger2中的 @Module
- single 單例模式
- factory 每次創(chuàng)建新的實(shí)例
- get()
3恐仑、Start Koin
class MyApplication : Application(){
override fun onCreate() {
super.onCreate()
startKoin{
androidLogger()
androidContext(this@MyApplication)
modules(appModule)
}
}
}
4灰署、依賴注入
class MySimpleActivity : AppCompatActivity() {
// Lazy injected
val firstPresenter: MySimplePresenter by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//...
}
}
// 更多方式
// non lazy
val firstPresenter: MySimplePresenter = get()
// lazy inject
private val homePresenter by inject<HomePresenter>()
// non lazy
private val homePresenter = get<HomePresenter>()
- by inject()
三判帮、ViewModel使用
1、創(chuàng)建被注入組件
interface HelloRepository {
fun giveHello(): String
}
class HelloRepositoryImpl() : HelloRepository {
override fun giveHello() = "Hello Koin"
}
class MyViewModel(val repo : HelloRepository) : ViewModel() {
fun sayHello() = "${repo.giveHello()} from $this"
}
2溉箕、創(chuàng)建module
val appModule = module {
// single instance of HelloRepository
single<HelloRepository> { HelloRepositoryImpl() }
// MyViewModel ViewModel
viewModel { MyViewModel(get()) }
}
3晦墙、Start Koin 同上面的Start Koin
4、依賴注入
class MyViewModelActivity : AppCompatActivity() {
// Lazy Inject ViewModel
val myViewModel: MyViewModel by viewModel()
// non lazy
//val myViewModel: MyViewModel = getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_simple)
//...
}
}
- viewModel:special DSL keyword to declare a ViewModel
- by viewModel() & getViewModel():to inject ViewModel instance (from Activity & Fragment)
- by sharedViewModel() & getSharedViewModel():to reuse ViewModel instance from hosting Activity (from Fragment)
四肴茄、Scope
val appModule = module {
// single instance of HelloRepository
single<HelloRepository> { HelloRepositoryImpl() }
// Scoped MyScopePresenter instance
scope(named<MyScopeActivity>()) {
scoped { MyScopePresenter(get()) }
}
}
class MyScopeActivity : AppCompatActivity() {
// inject MyScopePresenter from current scope
val scopePresenter: MyScopePresenter by currentScope.inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_simple)
}
}
The currentScope allows us to retrieve/create a Koin scope for given activity
五晌畅、其他
1、在module中使用 context
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
// use AndroidLogger as Koin Logger - default Level.INFO
androidLogger()
// use the Android context given there
androidContext(this@MainApplication)
}
}
module {
single { MyAndroidComponent(androidContext()) }
}
2寡痰、named使用
val myModule = module {
single<Service>(named("default")) { ServiceImpl() }
single<Service>(named("test")) { ServiceImpl() }
}
val service : Service by inject(name = named("default"))
val myModule = module {
single<Service> { ServiceImpl1() }
single<Service>(named("test")) { ServiceImpl2() }
}
Then:
val service : Service by inject() will trigger the ServiceImpl1 definition
val service : Service by inject(named("test")) will trigger the ServiceImpl2 definition
3踩麦、跨module使用
Koin does’t have any import concept. Koin definitions are lazy: a Koin definition is started with Koin container but is not instantiated. An instance is created only a request for its type has been done.
// ComponentB <- ComponentA
class ComponentA()
class ComponentB(val componentA : ComponentA)
val moduleA = module {
// Singleton ComponentA
single { ComponentA() }
}
val moduleB = module {
// Singleton ComponentB with linked instance ComponentA
single { ComponentB(get()) }
}
4、帶參數(shù)注入
單參數(shù)
class Presenter(val view : View)
val myModule = module {
single{ (view : View) -> Presenter(view) }
}
val presenter : Presenter by inject { parametersOf(view) }
多參數(shù)
class Presenter(val view : View, id : String)
val myModule = module {
single{ (view : View, id : String) -> Presenter(view,id) }
}
// inject with view & id
val presenter : Presenter by inject { parametersOf(this,id) }
5氓癌、 讀取 property
創(chuàng)建koin.properties
/src/main/resoucres/koin.properties
// Key - value
server_url=http://service_url
startKoin {
...
androidFileProperties()
...
}
val myModule = module {
// use the "server_url" key to retrieve its value
single { MyService(getProperty("server_url")) }
}
6谓谦、KoinComponent
Android中 inject() get()等方法在Activity和Fragment中已經(jīng)默認(rèn)存在;當(dāng)你在其他類中需要使用時(shí)贪婉,你需要讓其他類實(shí)現(xiàn)KoinComponent接口