Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Migrate to Koin

itome
December 13, 2018
280

Migrate to Koin

itome

December 13, 2018
Tweet

Transcript

  1. Dagger͔ΒKoinʹ৐Γ׵͑Δ
    Shibuya.apk #30

    View Slide

  2. ࣗݾ঺հ
    ௩ຊ෢ࢤ
    https://twitter.com/itometeam
    https://github.com/itome
    https://medium.com/@itometeam
    Cyberagent CATS
    1min

    View Slide

  3. Koinͱ͸ʁ
    7min

    View Slide

  4. Koinͱ͸ʁ
    7min
    ɾKotlin੡ͷܰྔDIϥΠϒϥϦ
    ɾno proxy, no code generation, no reflection!
    ɾReady for ViewModel
    ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    ɾEasy testing

    View Slide

  5. Koinͱ͸ʁ
    ɾKotlin੡ͷܰྔDIϥΠϒϥϦ
    ɾno proxy, no code generation, no reflection!
    ɾReady for ViewModel
    ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    ɾEasy testing
    7min

    View Slide

  6. Koinͱ͸ʁ
    ɾKotlin੡ͷܰྔDIϥΠϒϥϦ
    // Add Jcenter to your repositories if needed
    repositories {
    jcenter()
    }
    dependencies {
    // Koin for Android
    compile 'org.koin:koin-android:1.0.2'
    }
    Daggerͱಉ༷ʹAndroidݶఆϥΠϒϥϦͰ͸ͳ͍ͨΊɺ
    Spark΍KtorͳͲͷαʔόʔαΠυKotlinͰ΋ར༻Մೳ
    koin-androidϞδϡʔϧΛbuild.gradleʹهड़͢Δ͜ͱͰAndroidͰར༻Ͱ͖Δ
    υΩϡϝϯτ͕ॆ࣮͍ͯ͠ΔͷͰɺDIͷ֓೦Λཧղ͍ͯ͠Ε͹͙͢ʹ࢖͍࢝ΊΒΕΔ
    7min

    View Slide

  7. Koinͱ͸ʁ
    ɾKotlin੡ͷܰྔDIϥΠϒϥϦ
    ɾno proxy, no code generation, no reflection!
    ɾReady for ViewModel
    ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    ɾEasy testing
    7min

    View Slide

  8. ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    val appModule = module {
    // single instance of HelloRepository
    single { HelloRepositoryImpl() }
    // Simple Presenter Factory
    factory { MySimplePresenter(get()) }
    }
    module಺ʹscopeؔ਺Λهड़ͯ͠ґଘੑΛ௥Ճ͍ͯ͘͠
    single: ΞϓϦέʔγϣϯͱಉ͡ϥΠϑαΠΫϧΛ࣋ͭΠϯελϯεΛ
    ࡞੒͢Δ ɻ
    factory: ඞཁʹͳΔͨͼʹผͷΠϯελϯεΛ࡞੒͢Δɻ
    scope: ΧελϜείʔϓΛఆٛͰ͖Δɻ
    Koinͱ͸ʁ
    7min

    View Slide

  9. ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    val appModule = module {
    // single instance of HelloRepository
    single { HelloRepositoryImpl() }
    // Simple Presenter Factory
    factory { MySimplePresenter(get()) }
    }
    Koinͱ͸ʁ
    Daggerͱҧ͍ɺґଘάϥϑʹ͋ΔܕΛConstructor Injection͢Δ͚ͩͷ৔߹Ͱ΋ɺ
    ఆٛͷίʔυΛmoduleʹॻ͔ͳͯ͘͸ͳΒͳ͍
    ͢Ͱʹґଘੑ͕ఆٛ͞Ε͍ͯΔΫϥε͸ get()ͰऔಘͰ͖ΔͷͰɺ
    Constructor Injection͢Δͱ͖͸Ҿ਺ͷ਺͚ͩget()Λॻ͚ͩ͘Ͱ͍͍
    7min

    View Slide

  10. ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    Koinͱ͸ʁ
    class MainApplication : Application() {
    override fun onCreate() {
    super.onCreate()
    // start Koin context
    startKoin(this, listOf(appModule)
    }
    }
    ApplicationΫϥεͷonCreateͰ startKoin ʹModuleͷϦετΛ౉͢͜ͱͰ
    ґଘੑάϥϑ͕࡞੒͞ΕΔɻ
    7min

    View Slide

  11. Koinͱ͸ʁ
    ɾKotlin੡ͷܰྔDIϥΠϒϥϦ
    ɾno proxy, no code generation, no reflection!
    ɾReady for ViewModel
    ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    ɾEasy testing
    7min

    View Slide

  12. Koinͱ͸ʁ
    ɾno proxy, no code generation, no reflection!
    Koin͸࣮ࡍͷґଘੑͷ஫ೖΛKotlinͷDelegateΛ࢖࣮ͬͯݱ͍ͯ͠ΔͨΊɺDaggerͷΑ͏ͳ
    ίʔυੜ੒͕ඞཁͳ͍
    val appModule = module {
    single { HelloServiceImpl(get()) }
    }
    class MyActivity : AppCompatActivity(){
    val presenter : MyPresenter by inject()
    }
    ؔ਺ʹΑͬͯґଘੑͷ஫ೖ͕Ͱ͖ΔͨΊɺonCreateͳͲͰ໌ࣔతʹ
    inject
    injectΛݺͿඞཁ͕ͳ͍
    7min

    View Slide

  13. Koinͱ͸ʁ
    ɾKotlin੡ͷܰྔDIϥΠϒϥϦ
    ɾno proxy, no code generation, no reflection!
    ɾReady for ViewModel
    ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    ɾEasy testing
    7min

    View Slide

  14. Koinͱ͸ʁ
    ɾReady for ViewModel
    AACͷViewModelΛσϑΥϧτͰαϙʔτ͍ͯ͠Δ
    class MyActivity : AppCompatActivity(){
    // Lazy inject MyViewModel
    val model : MyViewModel by viewModel()
    }
    ͷ୅ΘΓʹ by viewModel()
    by inject() Λ࢖͏͜ͱͰ
    ViewModelProvider͔ΒViewModelͷΠϯελϯεΛऔಘͯ͘͠ΕΔ
    ಉҰͷActivityʹଐ͢Δෳ਺ͷFragmentؒͰViewModelΛڞ༗͍ͨ͠ͱ͖͸ɺ୅ΘΓʹ
    by sharedViewModel() Λ࢖͏
    7min

    View Slide

  15. Koinͱ͸ʁ
    ɾKotlin੡ͷܰྔDIϥΠϒϥϦ
    ɾno proxy, no code generation, no reflection!
    ɾReady for ViewModel
    ɾKotlin DSLΛ࢖ͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ
    ɾEasy testing
    7min

    View Slide

  16. Koinͱ͸ʁ
    ɾEasy testing
    class MyTest : KoinTest {
    // Lazy inject property
    val componentB : ComponentB by inject()
    @Test
    fun `should inject my components`() {
    startKoin(listOf(appModule)))
    // directly request an instance
    val componentA = get()
    assertNotNull(a)
    assertEquals(componentA, componentB.a)
    }
    }
    KoinTestΛܧঝͨ͠ςετΫϥεͷதͰຊ൪ͱಉ༷ʹ startKoin ͕Ͱ͖Δ
    7min

    View Slide

  17. Koinͱ͸ʁ
    ɾEasy testing
    @Test
    fun `check module`() {
    checkModules(listOf(appModule)))
    }
    Ϟδϡʔϧ಺ͷґଘੑ͕ղܾ͞Ε͍ͯΔ͔ͷςετ΋Ͱ͖Δ
    7min

    View Slide

  18. Dagger → Koin
    3min

    View Slide

  19. Dagger → Koin
    3min
    ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    ɾந৅ΫϥεΛ஫ೖ͍ͨ͠
    ɾಉ͡ܕʹผͷΠϯελϯεΛ஫ೖ͍ͨ͠
    ɾModuleΛ֊૚Խ͍ͨ͠

    View Slide

  20. Dagger → Koin
    3min
    ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    ɾந৅ΫϥεΛ஫ೖ͍ͨ͠
    ɾಉ͡ܕʹผͷΠϯελϯεΛ஫ೖ͍ͨ͠
    ɾModuleΛ֊૚Խ͍ͨ͠

    View Slide

  21. ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    3min Dagger → Koin
    factory, single, scopeؔ਺Λ࢖ͬͯείʔϓΛ੍ޚ͢Δ
    ஫ೖͷͨͼʹΠϯελϯε࡞੒
    Dagger @Provides
    fun provideMyPresenter(): MyPresenter = …
    Koin factory { MyPresenter() }

    View Slide

  22. ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    3min Dagger → Koin
    factory, single, scopeؔ਺Λ࢖ͬͯείʔϓΛ੍ޚ͢Δ
    ΞϓϦέʔγϣϯ୯ҐͰڞ௨ͷΠϯελϯεΛ࢖͏
    Dagger
    @Provides
    @Singleton
    fun provideRetrofit(
    okHttpClient: OkHttpClient
    ): Retrofit
    Koin single { Retrofit.Builder()… }

    View Slide

  23. ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    3min Dagger → Koin
    factory, single, scopeؔ਺Λ࢖ͬͯείʔϓΛ੍ޚ͢Δ
    ΧελϜείʔϓΛఆٛ
    Dagger
    @Scope
    @Retention(AnnotationRetention.RUNTIME)
    annotation class ActivityScope
    @Subcomponent
    @ActivityScope
    interface MyActivitySubcomponent {
    ...
    }
    Koin scope(“MyActivity”) { … }

    View Slide

  24. Dagger → Koin
    3min
    ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    ɾந৅ΫϥεΛ஫ೖ͍ͨ͠
    ɾಉ͡ܕʹผͷΠϯελϯεΛ஫ೖ͍ͨ͠
    ɾModuleΛ֊૚Խ͍ͨ͠

    View Slide

  25. ɾModuleΛ֊૚Խ͍ͨ͠
    3min Dagger → Koin
    Dagger
    @Subcomponent
    interface MyActivitySubcomponent {…}
    @Module(subcomponents = MyActivitySubcomponet::class.java)
    class MyActivityModule {}
    @Component(modules = [MyActivityModule::class.java])
    interface MyActivityComponent {…}
    Koin
    module("MyActivity") {
    module("MyActivitySub") {

    }
    }

    View Slide

  26. Dagger → Koin
    3min
    ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    ɾந৅ΫϥεΛ஫ೖ͍ͨ͠
    ɾಉ͡ܕʹผͷΠϯελϯεΛ஫ೖ͍ͨ͠
    ɾModuleΛ֊૚Խ͍ͨ͠

    View Slide

  27. ɾந৅ΫϥεΛ஫ೖ͍ͨ͠
    3min Dagger → Koin
    Dagger
    @Binds
    fun bindUserApi(
    userApiClient: UserApiClient
    ): UserApi
    Koin single { UserApiClient() } bind UserApi::class

    View Slide

  28. Dagger → Koin
    3min
    ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠
    ɾந৅ΫϥεΛ஫ೖ͍ͨ͠
    ɾಉ͡ܕʹผͷΠϯελϯεΛ஫ೖ͍ͨ͠
    ɾModuleΛ֊૚Խ͍ͨ͠

    View Slide

  29. ɾಉ͡ܕʹผͷΠϯελϯεΛ஫ೖ͍ͨ͠
    3min Dagger → Koin
    Dagger
    @Provides
    @Named("debug-client")
    fun provideDebugApiClient(retrofit: Retrofit): ApiClient
    @Provides
    @Named("prod-client")
    fun provideProdApiClient(retrofit: Retrofit): ApiClient
    Koin
    single("debug-client") { ApiClient() }
    single("prod-client") { ApiClient() }

    View Slide

  30. ϝϦοτɾσϝϦοτ
    3min

    View Slide

  31. ɾϝϦοτ
    3min ϝϦοτɾσϝϦοτ
    Daggerʹൺ΂ͯґଘੑͷهड़ํ๏͕؆ܿͰɺΘ͔Γ΍͍͢
    Field InjectionͷͨΊʹม਺Λpublicʹ͢Δඞཁ͕ͳ͍
    AACͷViewModelͷInjectionʹରԠ͍ͯ͠Δ
    ίʔυੜ੒ΛߦΘͳ͍ͷͰɺίϯύΠϧ࣌ؒ୹ॖ͕ݟࠐΊΔ
    ϚϧνϞδϡʔϧϓϩδΣΫτ΁ͷಋೖ͕؆୯

    View Slide

  32. ɾσϝϦοτ
    3min ϝϦοτɾσϝϦοτ
    ґଘੑͷղܾΛίϯύΠϧ࣌ʹ͢ΔDaggerʹൺ΂ͯϥϯλΠϜ͕஗͍
    ґଘੑͷॆ଍ʹࣦഊͨ͠ͱ͖ʹϥϯλΠϜΤϥʔͰམͪΔ͜ͱ͕͋Δ
    →ґଘੑͷॆ଍ʹ͍ͭͯ͸ςετ͕Ͱ͖ΔͨΊɺ੡඼൛Ͱى͜Δ֬཰͸Լ͛ΒΕΔ
    https://github.com/Sloy/android-dependency-injection-performance
    → moduleఆٛʹcreateOnStart=falseΛ౉͢͜ͱͰΠϯελϯεԽΛ஗ԆͰ͖Δ

    View Slide

  33. ·ͱΊ
    1min

    View Slide

  34. ͋Γ͕ͱ͏͍͟͝·ͨ͠
    Shibuya.apk #30
    https://twitter.com/itometeam
    https://github.com/itome
    https://medium.com/@itometeam
    Cyberagent CATS
    ௩ຊ ෢ࢤ

    View Slide