Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

Koinͱ͸ʁ 7min

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

ɾ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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Dagger → Koin 3min

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

ɾ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") { … } }

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

ɾಉ͡ܕʹผͷΠϯελϯεΛ஫ೖ͍ͨ͠ 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() }

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

·ͱΊ 1min

Slide 34

Slide 34 text

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