Koinμ μ΄λ»κ² μ°λμ§ μμλ΄ μλΉ~~
μμ±μ: μ΄μ’ ν
Present Time: 2018-11-9 FRI
koinμ΄ λ¬΄μμΈμ§ μμ보기 μ μ μ μ΄μ μμ μ΄ λ¬΄μμΈμ§ μμλ΄ μλ€.
νλ‘μ νΈκ° 컀μ§λ©΄ 컀μ§μλ‘ νλ‘κ·Έλ¨μμ μ μ΄ν΄μΌν λΆλΆμ λ§μμ§λ©° μ½λ κ΄λ¦¬κ° μ μ νλ€μ΄μ§λλ€. κ·Έλμ μ μ΄μ μμ μ΄λΌλ λ°©λ²μ μ΄μ©νμ¬ μ½λλ₯Ό κ΄λ¦¬ν©λλ€.
**μ μ΄μ μμ (Inversion of Control)**μ νλ μμν¬μ κ°μ²΄ μ¬μ© λ° μμ± λ± μ μ΄μ κΆνμ λκΈ°λ©° ν΄λΌμ΄μΈνΈκ° μ κ²½μ¨μΌν κ²μ μ€μ΄λ λ°©λ²μ λλ€.
μ μ΄μ μμ ꡬ쑰λ₯Ό ꡬνν λμλ λνμ μΈ λ°©λ²μΌλ‘ **μμ‘΄μ± μ£Όμ (Dependency Injection)**κ³Ό **μλΉμ€ λ‘μΌμ΄ν°(Service Locator)**κ° μμ΅λλ€.
class Car{
val tire = Tire()
val engine = Engine()
}
μμ κ°μ μ½λλ κ°μ²΄λ₯Ό Car
ν΄λμ€ λ΄λΆμμ μμ‘΄ κ°μ²΄λ₯Ό μμ±νκ² λ©λλ€. νμ§λ§ tire
μ engine
μ λ΄λΆμμ μμ±ν©λλ€. νμ§λ§ μ΄λ° λ°©λ²μ λͺ¨λκ°μ κ²°ν©λκ° λκ³ , Mock Objectλ₯Ό μ¬μ©νκΈ° νλ€κΈ° λλ¬Έμ ν
μ€ν
μ ν λ μ©μ΄νμ§ μμ μ μμ΅λλ€.
val car = Car()
car.tire = Tire()
car.engine = Engine()
val car2 = Car(Tire(), Engine())
μμ²λΌ μΈλΆλ‘λΆν° κ°μ²΄λ₯Ό λ°μμ€κ² λλ©΄ κ²°ν©λκ° λ¨μ΄μ§κ³ , ν μ€ν μ ν κ²½μ°μλ Mock Objectλ₯Ό μ£Όμ νλ©΄ λκΈ° λλ¬Έμ ν μ€νΈκ° λ μ©μ΄ν΄μ§λλ€.
DI νλ μμν¬λ μμ²λΌ κ°μ²΄λ₯Ό μμ±νκ³ λ겨주며 κ°μ²΄μ μ μ΄λ₯Ό νλ μμν¬μμ νκ² λλλ°, μ΄λ IoC κ°λ μ ꡬνν©λλ€.
λ³΄ν΅ Springκ°μ νλ μμν¬λ₯Ό μ΄μ©νμ¬ DIλ₯Ό μ¬μ©ν©λλ€.
μλλ‘μ΄λλ Dagger2λΌλ νλ μμν¬λ₯Ό μ΄μ©νμ¬ DIλ₯Ό ꡬνν©λλ€.
Service Locatorλ, μμ‘΄μ±μ΄ νμ ν λ, μΈλΆμμ ν΄λμ€λ₯Ό λ°μμμ μ¬μ©νλ λ°©μμ λλ€.
class Car{
val car = Locator.resolve<Car>()
}
class Locator{
// μ΄νμλ΅
}
μμ²λΌ Locator
ν΄λμ€μμ κ°μ²΄λ₯Ό λ°μμ μ¬μ©νμ¬λ κ²°ν©λλ₯Ό λ¨μ΄λ¨λ¦¬κ³ ν
μ€νΈνκΈ° μ©μ΄ν μ½λλ₯Ό μμ±ν μ μμ΅λλ€.
λ¬Όλ‘ μ€μ DI, Service Locator νλ μμν¬λ μ μ½λλ³΄λ€ ν¨μ¬ μ’μ λ°©λ²μΌλ‘ ꡬμ±λμ΄ μκ² μ§λ§, μ΄λ²μλ μ΄ν΄λ₯Ό λκΈ° μν΄ μ΄λ° μμ λ₯Ό μ¬μ©νμμ΅λλΉ~~~
νλ μμν¬μμ κ°μ²΄λ₯Ό κ΄λ¦¬νκ² λλ©° μ¬λ¬κ°μ§ μ΄μ μ μ»κ² λ©λλ€.
- λ€λ₯Έ μμ€ν μ΄ λ¬΄μμ ν μ§ μΆμΈ‘μ νμ§ μμλ λ©λλ€.
- μμ€ν μ λ°κΏλ λ€λ₯Έ μμ€ν μ μ§μ₯μ μ£Όμ§ μμ΅λλ€.
λ§ν΄ νμΈλ¬κ° μ΄ Inversion of Control Containers and the Dependency Injection patternμ΄λΌλ κΈμ μ½μ΄λ³΄λ©΄,
As a result I think we need a more specific name for this pattern. Inversion of Control is too generic a term, and thus people find it confusing. As a result with a lot of discussion with various IoC advocates we settled on the name Dependency Injection.
λΌλ ꡬμ μ΄ μμ΅λλ€.
IoCλΌλ λ¨μ΄κ° λ무 λͺ¨νΈνμ¬ κ·Έλ₯ μμΌλ‘λ **DI(Dependency injection)**μ΄λΌλ λ¨μ΄λ₯Ό μ¬μ©νμκ³ νμμΌλκΉ μ΄λ² μ 리μμλ κ·Έλ₯ λͺ¨λ ν΅νμ΄ DIλΌκ³ λ§ν κ²μ
Koinμ DSLλ‘ μ΄λ£¨μ΄μ§ μμ‘΄μ± μ£Όμ νλ μμν¬μ λλ€.
λͺ¨λ λ€ μ½νλ¦°μΌλ‘ μμ±λμκ³ , μ½νλ¦°μΌλ‘λ§ μ¬μ©ν μ μμ΅λλ€.
Daggerλ μ΄λ Έν μ΄μ , ν΄λμ€ κΈ°λ°μΌλ‘ μ½κ° κ°λ μ±μ΄ λ¨μ΄μ§μ§λ§, μ΄λ Έν μ΄μ νλ‘μΈμλ₯Ό μ΄μ©νμ¬ μ»΄νμΌ λ¨μμμ μ€λ₯λ₯Ό μ‘μλΌ μ μμ΅λλ€.
koinμ DSL κΈ°λ°μΌλ‘ μ΄λ£¨μ΄μ Έ μμ΄ κ°λ μ±μ΄ μ’κ³ , κ°μ²΄λ₯Ό μ£Όμ ν λ byλ₯Ό μ΄μ©νμ¬ μ§μ° λ°©μμ μ¬μ©ν μ μμ΅λλ€. νμ§λ§ μ€λ₯λ₯Ό μ»΄νμΌμμ μ‘μλΌ μ μκ³ λ°νμμμ μ€λ₯λ₯Ό μ‘μλΌ μ μμ΅λλ€. λν, μλΉμ€ λ‘μΌμ΄ν° ν¨ν΄μ μ¬μ©ν©λλ€.
koinμμλ Moduleμ νμν μμ‘΄μ±μ μ μνλ©° μ€κ³ν©λλ€.
λͺ¨λμ μ μνλλ²μ λ€μκ³Ό κ°μ΅λλ€.
val module = module {
}
module
λ λ§μ°¬κ°μ§λ‘ DSL νμμΌλ‘ μ¬μ©ν μ μκΈ° λλ¬Έμ, κ°λ
μ±μ΄ λμ΅λλ€.
λͺ¨λμ μ μνκ³ , λͺ¨λ μμ λ€μ΄κ° μμ‘΄μ±μ μ μν©λλ€.
λͺ¨λ μμμ μμ‘΄μ±μ μ μνκ³ , μ°¨νμ ν΄λΌμ΄μΈνΈμμ inject()
, viewModel()
λ±μ ν€μλλ₯Ό μ΄μ©νμ¬ λͺ¨λλ‘λΆν° μμ‘΄μ±μ μ£Όμ
λ°μ΅λλ€.
μ¬μ©ν μ μλ ν€μλλ λ€μκ³Ό κ°μ΅λλ€.
factory
:inject()
κ° νΈμΆλ λ λ§λ€ μλ‘μ΄ κ°μ²΄λ₯Ό λ§λ€μ΄μ€λλ€.single
:inject()
κ° νΈμΆλ λ, μ±κΈν€ κ°μ²΄λ₯Ό μ£Όμ ν΄μ€λλ€.viewModel
: AACμ ViewModelμ μ¬μ©ν λ μ°λ ν€μλλ‘,ViewModelProviders
λ₯Ό ν΅νμ¬ μλͺ μ£ΌκΈ°μ μμ ν ViewModelμ μ£Όμ ν΄μ€λλ€.get():
λͺ¨λμμ κ° μ»΄ν¬λνΈλΌλ¦¬μ μμ‘΄μ± μ£Όμ μ μν΄ μ°μ΄λ ν€μλμ λλ€.
μ΄μΈμλ μ¬λ¬ ν€μλλ₯Ό ν΅ν΄μ μμ‘΄μ±μ μ μνκ³ , ν΄λΌμ΄μΈνΈμμ μμ‘΄μ±μ μ£Όμ ν©λλ€.
λͺ¨λμμ μ μν μμ‘΄μ±μ νμν κ³³μ μ£Όμ ν©λλ€. Dagger2μ λ¬λ¦¬ μμ νλ‘νΌν°λ₯Ό μ¬μ©ν μλ μκ³ , κ·Έλ₯ λ°μμ¬ μλ μμ΅λλ€.
μ¬μ©νλ ν€μλλ λ€μκ³Ό κ°μ΅λλ€.
by inject()
: μμ νλ‘νΌν°λ₯Ό μ΄μ©νμ¬ νΈμΆλ μμ μ μμ‘΄μ±μ μ£Όμ λ°μ΅λλ€.by viewModel()
: μμ νλ‘νΌν°λ₯Ό μ΄μ©νμ¬ νΈμΆλ μμ μ λ·°λͺ¨λΈμ μ£Όμ λ°μ΅λλ€. λͺ¨λμμviewModel
μ μ μνμ λ μ¬μ©ν©λλ€.by sharedViewModel()
: μμ κ°μ λμμ μννμ§λ§, νλκ·Έλ¨ΌνΈμμλ§ μ¬μ©ν μ μκ³ μ‘ν°λΉν° μλμμ 곡μ ν μ μλ λ·°λͺ¨λΈμ μ£Όμ λ°μ΅λλ€.getViewModel(), getSharedViewModel()
: μμ νλ‘νΌν°λ₯Ό μ¬μ©νμ§ μκ³ , μμ μΉκ΅¬λ€μ κ·Έλ₯ λ°λ‘ λ°μμ΅λλ€.
μ§~λλ²μ μμλ‘ λ€μλ MVP μ½λμ koinμ μ μ©ν΄λ΄ μλ€~~
def koin_version = '1.0.1'
// Koin for Android
implementation "org.koin:koin-android:$koin_version"
// Koin Android Scope feature
implementation "org.koin:koin-android-scope:$koin_version"
// Koin Android ViewModel feature
implementation "org.koin:koin-android-viewmodel:$koin_version"
- λͺ¨λ λ¨μ
build.gradle
μdependencies
μ μμ κ°μ μμ‘΄μ±μ μΆκ°ν©λλ€. - μ±ν¬νλ©΄ μμ±~~
val mainModule = module {
factory { MainPresenter(get()) }
single { MainRepository() }
}
class MainPresenter(val repository: MainRepository) : MainContract.Presenter {
}
-
μ½νλ¦°μμλ κΌ ν΄λμ€λ₯Ό λ§λ€ νμκ° μκΈ° λλ¬Έμ, ν΄λμ€λ₯Ό μ μνμ§ μκ³ νμΌλ§ λ§λ€μ΄ κ·Έκ³³μ λͺ¨λλ€μ μ μνλ λ°©λ²μ μ¬μ©ν©λλ€.
-
MainActivity
μμMainPresenter
μμ‘΄μ±μ λ°μμμΌ νκΈ° λλ¬Έμ mainModuleμMainPresnter
λ₯Ό μ μν©λλ€. -
νλ μ ν°λ
factory
ν€μλλ₯Ό μ΄μ©νμ¬,inject()
κ° νΈμΆλ λ λ§λ€ μλ‘μ΄ κ°μ²΄λ₯Ό λ°μμ€κ²λ νμ΅λλ€. -
λ ν¬μ§ν 리 ν΄λμ€λ
single
ν€μλλ₯Ό μ΄μ©νμ¬ μ±κΈν€μΌλ‘ μ μν©λλ€. -
MainPresenter
λ μμ±μλ‘MainRepository
λ₯Ό λ°μ΅λλ€. μμ‘΄μ±μget()
ν€μλλ₯Ό μμ±μ μμ μμ±ν΄λλ©΄ koinμ΄ μμμ μμ‘΄μ±μ μ°Ύμμ λ£μ΄μ€λλ€.
Application
μ μμλ°λ ν΄λμ€λ₯Ό λ§λ€κ³ , onCreate()
μ startKoin()
μ μμ±ν©λλ€.
class App : Application() {
override fun onCreate() {
super.onCreate()
startKoin(this, listOf(mainModule))
}
}
startKoin()
μ μΈμμλ contextμ μ μν΄λ λͺ¨λ 리μ€νΈκ° λ€μ΄κ°λλ€.
thisμ listof
ν€μλλ₯Ό μ΄μ©νκ±°λ, 미리 μ μν΄λ λͺ¨λ 리μ€νΈλ₯Ό μΈμλ‘ λ£μ΄μ€λλ€.
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:name=".App"
android:supportsRtl="true"
android:theme="@style/AppTheme">
κ·Έ λ€μμ λ©λνμ€νΈμ μ΄ν리μΌμ΄μ
νκ·Έμ android:name
μμ±μ λ°©κΈ λ§λ μ΄ν리μΌμ΄μ
μ μ μν΄μ€λλ€.
class MainActivity : AppCompatActivity(), MainContract.View {
val presenter: MainPresenter by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
presenter.view = this
}
}
μ μν΄λ λͺ¨λμ by inject()
λ₯Ό μ΄μ©νμ¬ μ£Όμ
λ°μ΅λλ€.
μ! λμ λλΉ~~