Kotlin Koin
Kotiln Koin
Koin은 Kotlin 개발자를 위한 실용적인 경량 종속성 주입 프레임워크로 순수한 Kotlin 언어로 작성되었으며 함수 파싱만 사용하고 프록시, 코드 생성 및 리플렉션이 없습니다.
코인이 리플렉션을 사용할 필요가 없는 이유는?
Koin은 kotlin을 기반으로 개발되었기 때문에 kotlin의 강력한 구문(예: Inline, Reified 등)과 함수형 프로그래밍을 사용하여 간단한 예제를 살펴보겠습니다.
Koin설정법은 여기를 참고하세요.
https://yunhos.blogspot.com/2021/05/kotlin-koin.html
설정 3.1.2
```plain
dependencies {
def koin_version = "3.1.2"
// Koin main features for Android (Scope,ViewModel ...)
implementation "io.insert-koin:koin-android:$koin_version"
// Koin Java Compatibility
implementation "io.insert-koin:koin-android-compat:$koin_version"
// Koin for Jetpack WorkManager
implementation "io.insert-koin:koin-androidx-workmanager:$koin_version"
// Koin for Jetpack Compose
implementation "io.insert-koin:koin-androidx-compose:$koin_version"
}
1. Application DSL
KoinApplication
코인 주입 항목을 구성하기 위해 다음 API를 사용할 수 있습니다.
koinApplication { }
: 코인 컨테이너를 생성합니다.startKoin { }
: Koin 컨테이너 를 생성 하고 에 등록합니다GlobalContext
하여GlobalContext
의 API 를 사용할 수 있습니다 .logger( )
: 사용할 로그 모드를 선택할 수 있습니다. Koin은 AndroidLogger , PrintLogger , EmptyLogger 등 3개의 기본 로거를 제공하며 , 모두 추상 클래스 Logger 에서 상속 합니다. 구성되지 않은 경우 기본적으로 EmptyLogger가 사용됩니다. 즉, 인쇄하지 않습니다.modules( )
: 코인 모듈을 구성하고 코인 컨테이너에 주입합니다.properties()
: HashMap을 사용하여 전역 쿼리 수정을 위한 속성을 삽입합니다.fileProperties( )
: 주어진 속성 파일을 사용하여 속성을 주입합니다. 파일은 src/main/resources 디렉토리에 있어야 합니다.environmentProperties( )
: 주입을 통해 시스템 및 환경 속성을java.lang.System
주입 합니다.
2. Module DSL
module { // module content }
: 코인 모듈을 생성합니다.factory { //definition }
: 주입된 클래스의 인스턴스를 생성합니다.single { //definition }
: 싱글톤을 생성한다는 점을 제외하고 와 동일한factory
기능 입니다.get()
: 구성 요소 종속성을 해결하여 클래스 인스턴스를 주입합니다.inject()
:get()
함수 둘 다 클래스 주입을 제공하지만inject
지연 로딩을 제공합니다.bind()
: 기본 주입 클래스는 하나의 유형에만 대응할 수 있으므로 주입된 클래스에 유형 바인딩을 추가합니다.binds()
: 기능은 위와bind()
동일하고 여러개에 여러 유형의 바인딩을 제공합니다.scope { // scope group }
: 주입된 클래스의 수명 주기를 제어하는 역할을 하는 그룹을scoped
정의합니다 .scoped { //definition }
: 위의 내용scope
과 정의하여scope
의 범위 내에서만 존재함을 나타냅니다.named()
: 동일한 유형의 주입이 두 개 이상 발생하는 경우 이 기능을 사용하여 주입에 이름을 지정한 다음 주입에 이름을 지정하기만 하면 올바른 주사를 얻을 수 있습니다.
3. 사용법
Application클래스의 onCreate에서 startKoin을 불러내서 사용합니다.
super.onCreate()
startKoin {
androidContext(this@MyApplication) //`androidContext()`는 모듈 내에서 Context를 참조하려는 경우 호출합니다.
// startKoinAndroid 컨텍스트 에서 선언된 Android 컨텍스트 androidContext(this@MyApplication)는 실제로는 전역 주입 Context및 Application싱글톤입니다.
modules(module{
viewModel {SplashViewModel()}
})
}
Koin-android 라이브러리에는 안드로이드용 viewmodel을 이용할수있도록 미리 준비되어있기 때문에 ViewModel을 연결할경우 아래와 같이 간단하게 할수 있습니다.
-일반적인 뷰모델 클래스 작성
class SplashViewModel : ViewModel() {}
-Koin에서 사용하기 위해서 viewModel을 정의추가
modules(module{
viewModel {SplashViewModel()}
})
-필요한 곳(Activity, Fragment)에서 호출해서 사용
class SplashActivity : FragmentActivity(), KoinComponent {
val splashViewModel: SplashViewModel by viewModel()
이렇게 module{} 안에 등록하면 앱실행시에 Koin이 필요한 모듈을 찾아서 사용할 준비를 해줍니다.
모듈을 정의할때 single, factory, viewModel등이 있는데 다음과 갔습니다.
선언의예
val myModule = module {
//1
single{ A() }
//2
factory{ B() }
//3
factory{ C(get()) }
//4
single<F> { FImp() }
//5
single { FImp() } bind F::class
//6
single(named:("special")){ A() }
//7
single{ (view:View) -> D(view) }
//8
single(createdAtStart=true){ A() }
}
- single
- 전역 범위의 싱글톤 모드(기본적으로 지연 로딩)는 한 번 생성되면 전체 코인 수명 주기 동안 존재합니다.
module {
// 매개변수 없는 경우
single { User() }
// 재정의(override)해서 사용 할경우
single(override = true) { User() }
// 동일한 유형이지만 사용할때 이름으로 구분해서 사용할경우
single(named("a")) { User() }
single(named("b")) { User() }
// 주입시에 인수를 지정하는 방법과, 인수로서 위에 선언된 모듈을 get()으로 넘기는 경우(UseLoginProcess가3번째인자로 User클래스 타입을 요구할경우)
single { (phone: String, passWord: String) -> UseLoginProcess(phone, passWord, get()) }
}
- 사용할때는 (지연 로딩, 즉 소스내에서 호출할때 로딩)
val user:User by inject()
val user:User by inject(named("a"))
val useLoginProcess:UseLoginProcess by inject { parametersOf("1111","*****") }
바로 로딩
val user:User = get()
val usera:User = get(named("a"))
val loginBean:LoginBean=get { parametersOf("189****11","*****")
}
- factory
- 현재 범위의 팩토리 모드에서는 팩토리 메소드 소스 코드를 얻을 때마다 새 인스턴스가 생성됩니다.
module {
factory(User()}
// 이하 Single과 동일
}
- 사용할때는 (지연 로딩, 즉 소스내에서 호출할때 로딩)
val user:User by inject()
// 이하 Single과 동일
- viewModel
- 안드로이드의 viewModel을 쉽게 정의할수 있도록 해줍니다.
module {
viewModel{ TestViewModel() }
// 이하 Single과 동일
}
- 사용할때는 (지연 로딩, 즉 소스내에서 호출할때 로딩)
private val viewModel: TestViewModel by viewModel()
// 이하 Single과 동일
4.Bind
bind()함수는 동시에 바인딩하고자 하는 KClass 타입을 전달해야 하며, 동시에 바인딩해야 하는 타입이 여러 개인 경우 List 타입을 전달하는 binds()함수를 사용합니다.
// 클래스 타입을 명시해서 모듈을 추가할경우
factory<Engine> { GasEngine() }
// or
factory { GasEngine as Engine }
// `bind()` 를 사용할 경우
factory { GasEngine() } bind Engine::class
- bind 사용예
val module = module {
factory { GasEngine() } bind Engine::class
factory { ElectricEngine() } bind Engine::class
}
private val gasEngine = get<Engine>()
private val electricEngine = get<ElectricEngine>()
5. Qualifier
Qualifier한정자 는 구성 및 주입에 사용되며 factory(), single()함수 는 형식 매개변수를 제공했으며, 이는 함수named() 를 통해 얻을 수 있고 원하는 효과를 얻기 위해 전달할 수 있습니다.
named()3가지 사용 방법 지원:
- named(): 제네릭 인증
- named(String): 문자열로 한정
- named(Enum): 열거형으로 한정
val module = module {
factory(named("gas")) { 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"))
6. Scope
스코프는 수명 주기를 사용하는 주입을 제공합니다.
범위는 인스턴스의 범위이며 범위가 끝나면 인스턴스가 컨테이너에서 제거됩니다.
Scope 를 구성 할 때 scopeId 와 scopeName 을 지정해야 합니다 . (Qualifier 또는 제네릭을 사용할 수 있습니다 . 인젝션을 사용할 때 먼저 범위를 생성합니다.
다음 기능을 사용할 수 있습니다.
- createScope(): 범위 생성
- getScope: 범위를 가져옵니다. 존재하지 않으면 예외가 보고됩니다.
- getOrCreateScope: 범위 가져오기, 존재하지 않으면 생성하여 반환합니다.
0 comments:
댓글 쓰기