오늘도 더 나은 코드를 작성하였습니까?

Koin Definitions 본문

Koin

Koin Definitions

hik14 2022. 7. 28. 16:01

모듈 작성하기 Writing a module

코인 모듈은 모든 구성 component를 선언하는 공간입니다.

모듈 함수를 사용하여 코인 모듈을 선언합니다

val myModule = module {
   // your dependencies here
}

싱글톤 요소 정의 Defining a singleton

싱글톤 구성 component를 선언한다는 것은 Koin container가 선언된 구성 component 고유한 인스턴스를 유지한다는 것을 의미합니다. 모듈에서 single()  함수를 사용하여 싱글톤 선언

class MyService()

val myModule = module {

    // declare single instance for MyService class
    single { MyService() }
}

람다를 이용한 컴포넌트 정의 Defining your component within a lambda

single, factory 및 scope 키워드는 람다 식을 통해 component를 선언하는 데 도움이 됩니다.  

일반적으로 component 요소를 생성자를 통해 인스턴스화하지만 특정 표현식을 사용할 수도 있습니다.

 

single { Class constructor // Kotlin expression }

팩토리 요소 정의 Defining a factory

factory component 선언은 요청할 때마다 새 인스턴스를 제공하는 정의입니다(이 인스턴스는 나중에 다른 정의에 이 인스턴스를 삽입하지 않기 때문에 Koin 컨테이너에 유지되지 않습니다)

class Controller()

val myModule = module {

    // declare factory instance for Controller class
    factory { Controller() }
}

Resolving & injecting dependencies

이제 component 정의를 선언할 후, 종속성 주입으로 인스턴스를 연결하려고 합니다.

Koin module 에서 인스턴스를 이용하여 주입하려면, 요청된 필수 component 객체에 get() 함수를 사용하기만 하면 된다.

 get() 함수는 일반적으로 생성자 값을 주입하기 위해 생성자에 사용

 

*koin container로 의존성 주입을 하려면 생성자 주입 스타일로 작성해야 합니다.

클래스 생성자에서 의존성을 해결합니다. 이렇게 하면 인스턴스가 코인에서 주입된 인스턴스로 생성됩니다.

// 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()) }
}

Definition: binding an interface

single 또는 factory definition는 주어진 람다의 데이터 타입을 사용합니다.

즉, single { T } definition의 Data Type은 람다 표현식의 내의 T 이다.

// Service interface
interface Service{

    fun doSomething()
}

// Service Implementation
class ServiceImp() : Service {

    fun doSomething() { ... }
}

Koin 모듈에서 다음과 같이 as 캐스트 Kotlin 연산자를 사용

val myModule = module {

    // Will match type ServiceImp only
    single { ServiceImp() }

    // Will match type Service only
    single { ServiceImp() as Service }

}

inferred 유형 표현식을 사용할 수도 있습니다.

val myModule = module {

    // Will match type ServiceImp only
    single { ServiceImp() }

    // Will match type Service only
    single<Service> { ServiceImp() }

}

Additional type binding

하나의 Definition에서 여러 DataType을 일치시키기.

// Service interface
interface Service{

    fun doSomething()
}

// Service Implementation
class ServiceImp() : Service{

    fun doSomething() { ... }
}

definition에 추가적 Type에 바인딩 하기위해 ::class 와 함께  bind 연산자를 사용, 2개의 dataType에 매칭됨

val myModule = module {

    // Will match types ServiceImp & Service
    single { ServiceImp() } bind Service::class
}

여기서 우리는 get()을 사용하여 Service Type 을 직접 해결한다는 점에 유의하십시오.

Service를 바인딩하는 여러개 definition가 있는 경우 bind<>() 함수를 사용해야 합니다.

Definition: naming & default bindings

definitionname을 지정하면 동일한 유형에 대한 두 정의를 구별하는 데 도움이 됩니다. 

val myModule = module {
    single<Service>(named("default")) { ServiceImpl() }
    single<Service>(named("test")) { ServiceImpl() }
}

val service : Service by inject(qualifier = named("default"))

get() 및 injection() 함수를 사용하면 필요한 경우 definition name을 지정할 수 있습니다.

이름은 named() 함수에 의해 생성된 한정자입니다

 

Koin은 유형이 이미 정의에 바인딩되어 있는 경우 해당 Type 또는 Name으로 정의를 바인딩합니다

val myModule = module {
    single<Service> { ServiceImpl1() }
    single<Service>(named("test")) { ServiceImpl2() }
}
val service : Service by inject() will trigger the ServiceImpl1 definition
val service : Service by inject(named("test")) will trigger the ServiceImpl2 definition

 

주입 파라미터 Declaring injection parameters

모든 definition에서 parameter injection를 사용할 수 있습니다. definition에서 주입하고 사용할 매개변수

class Presenter(val view : View)

val myModule = module {
    single{ (view : View) -> Presenter(view) }
}

생성자 종속성(get()으로 해결됨)과 달리 parameter injection 는 해결 API를 통해 전달되는 매개변수입니다.

매개변수가 다음과 같이 parametersOf 함수와 함께 get() 및 injection()으로 전달된 값

val presenter : Presenter by inject { parametersOf(view) }

Using definition flags

Create instances at start

definition 또는 모듈은 CreatedAtStart로 플래그를 지정하여 시작할 때(또는 원하는 때) 만들 수 있습니다.

 

definition에 플래그 추가

val myModuleA = module {

    single<Service> { ServiceImp() }
}

val myModuleB = module {

    // eager creation for this definition
    single<Service>(createdAtStart=true) { TestServiceImp() }
}

 

모듈에 플래그 추가

val myModuleA = module {

    single<Service> { ServiceImp() }
}

val myModuleB = module(createdAtStart=true) {

    single<Service>{ TestServiceImp() }
}

startKoin 함수는 createdAtStart로 플래그가 지정된 정의 인스턴스를 자동으로 생성.

// Start Koin modules
startKoin {
    modules(myModuleA,myModuleB)
}

Dealing with generics

koin definition는  제네릭 타입 파라미터를 사용하지 않습니다.

예를 들어, 아래 모듈은 List의 2가지 정의를 정의하려고 한다.

module {
    single { ArrayList<Int>() }
    single { ArrayList<String>() }
}

Koin은 위와 definition로 실행할 수 없다.  

definition를 다른 definition로 ​​덮어쓰고 하기 때문이다.  

name 또는 위치(모듈)를 통해 구분해야 하는 2개의 definition를 사용합니다. 

module {
    single(named("Ints")) { ArrayList<Int>() }
    single(named("Strings")) { ArrayList<String>() }
}

'Koin' 카테고리의 다른 글

Koin (Scopes)  (0) 2022.07.28
Koin (Passing Parameters - Injected Parameters)  (0) 2022.07.28
Koin Component  (0) 2022.07.28
Koin Modules  (0) 2022.07.28
Koin이란?  (0) 2022.07.27