Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Migrate to Koin
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
itome
December 13, 2018
360
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Migrate to Koin
itome
December 13, 2018
More Decks by itome
See All by itome
今日始め るCloudflare Browser Rendering
itome
2
330
Android accessibility and automated check tools
itome
1
5.1k
Accessibility in CATS
itome
4
2.5k
Introduce_Owl.pdf
itome
0
120
Introducing Android Accessibility Test with Accessibility Testing Framework
itome
1
790
Introduction of accessibility for mobile development
itome
0
260
Architecture_for_mobile_development.pdf
itome
0
280
Android_Accessibility_Suite.pdf
itome
0
170
Introducing Owl
itome
0
1.2k
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.9k
The browser strikes back
jonoalderson
0
1.1k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
480
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
720
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Everyday Curiosity
cassininazir
0
220
Building the Perfect Custom Keyboard
takai
2
780
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
380
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
240
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
270
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Transcript
Dagger͔ΒKoinʹΓ͑Δ Shibuya.apk #30
ࣗݾհ ௩ຊࢤ https://twitter.com/itometeam https://github.com/itome https://medium.com/@itometeam Cyberagent CATS 1min
Koinͱʁ 7min
Koinͱʁ 7min ɾKotlinͷܰྔDIϥΠϒϥϦ ɾno proxy, no code generation, no reflection!
ɾReady for ViewModel ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ ɾEasy testing
Koinͱʁ ɾKotlinͷܰྔDIϥΠϒϥϦ ɾno proxy, no code generation, no reflection! ɾReady
for ViewModel ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ ɾEasy testing 7min
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ݶఆϥΠϒϥϦͰͳ͍ͨΊɺ SparkKtorͳͲͷαʔόʔαΠυKotlinͰར༻Մೳ koin-androidϞδϡʔϧΛbuild.gradleʹهड़͢Δ͜ͱͰAndroidͰར༻Ͱ͖Δ υΩϡϝϯτ͕ॆ࣮͍ͯ͠ΔͷͰɺDIͷ֓೦Λཧղ͍ͯ͠Ε͙͢ʹ͍࢝ΊΒΕΔ 7min
Koinͱʁ ɾKotlinͷܰྔDIϥΠϒϥϦ ɾno proxy, no code generation, no reflection! ɾReady
for ViewModel ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ ɾEasy testing 7min
ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ val appModule = module { // single instance
of HelloRepository single<HelloRepository> { HelloRepositoryImpl() } // Simple Presenter Factory factory { MySimplePresenter(get()) } } moduleʹscopeؔΛهड़ͯ͠ґଘੑΛՃ͍ͯ͘͠ single: ΞϓϦέʔγϣϯͱಉ͡ϥΠϑαΠΫϧΛ࣋ͭΠϯελϯεΛ ࡞͢Δ ɻ factory: ඞཁʹͳΔͨͼʹผͷΠϯελϯεΛ࡞͢Δɻ scope: ΧελϜείʔϓΛఆٛͰ͖Δɻ Koinͱʁ 7min
ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ val appModule = module { // single instance
of HelloRepository single<HelloRepository> { HelloRepositoryImpl() } // Simple Presenter Factory factory { MySimplePresenter(get()) } } Koinͱʁ Daggerͱҧ͍ɺґଘάϥϑʹ͋ΔܕΛConstructor Injection͢Δ͚ͩͷ߹Ͱɺ ఆٛͷίʔυΛmoduleʹॻ͔ͳͯ͘ͳΒͳ͍ ͢Ͱʹґଘੑ͕ఆٛ͞Ε͍ͯΔΫϥε get()ͰऔಘͰ͖ΔͷͰɺ Constructor Injection͢Δͱ͖Ҿͷ͚ͩget()Λॻ͚ͩ͘Ͱ͍͍ 7min
ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ Koinͱʁ class MainApplication : Application() { override fun
onCreate() { super.onCreate() // start Koin context startKoin(this, listOf(appModule) } } ApplicationΫϥεͷonCreateͰ startKoin ʹModuleͷϦετΛ͢͜ͱͰ ґଘੑάϥϑ͕࡞͞ΕΔɻ 7min
Koinͱʁ ɾKotlinͷܰྔDIϥΠϒϥϦ ɾno proxy, no code generation, no reflection! ɾReady
for ViewModel ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ ɾEasy testing 7min
Koinͱʁ ɾno proxy, no code generation, no reflection! Koin࣮ࡍͷґଘੑͷೖΛKotlinͷDelegateΛ࣮ͬͯݱ͍ͯ͠ΔͨΊɺDaggerͷΑ͏ͳ ίʔυੜ͕ඞཁͳ͍
val appModule = module { single<Hello> { HelloServiceImpl(get()) } } class MyActivity : AppCompatActivity(){ val presenter : MyPresenter by inject() } ؔʹΑͬͯґଘੑͷೖ͕Ͱ͖ΔͨΊɺonCreateͳͲͰ໌ࣔతʹ inject injectΛݺͿඞཁ͕ͳ͍ 7min
Koinͱʁ ɾKotlinͷܰྔDIϥΠϒϥϦ ɾno proxy, no code generation, no reflection! ɾReady
for ViewModel ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ ɾEasy testing 7min
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
Koinͱʁ ɾKotlinͷܰྔDIϥΠϒϥϦ ɾno proxy, no code generation, no reflection! ɾReady
for ViewModel ɾKotlin DSLΛͬͨ؆ܿͳهड़Ͱґଘੑ͕هड़Ͱ͖Δ ɾEasy testing 7min
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<ComponentA>() assertNotNull(a) assertEquals(componentA, componentB.a) } } KoinTestΛܧঝͨ͠ςετΫϥεͷதͰຊ൪ͱಉ༷ʹ startKoin ͕Ͱ͖Δ 7min
Koinͱʁ ɾEasy testing @Test fun `check module`() { checkModules(listOf(appModule))) }
Ϟδϡʔϧͷґଘੑ͕ղܾ͞Ε͍ͯΔ͔ͷςετͰ͖Δ 7min
Dagger → Koin 3min
Dagger → Koin 3min ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ ɾநΫϥεΛೖ͍ͨ͠ ɾಉ͡ܕʹผͷΠϯελϯεΛೖ͍ͨ͠ ɾModuleΛ֊Խ͍ͨ͠
Dagger → Koin 3min ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ ɾநΫϥεΛೖ͍ͨ͠ ɾಉ͡ܕʹผͷΠϯελϯεΛೖ͍ͨ͠ ɾModuleΛ֊Խ͍ͨ͠
ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ 3min Dagger → Koin factory, single, scopeؔΛͬͯείʔϓΛ੍ޚ͢Δ ೖͷͨͼʹΠϯελϯε࡞ Dagger
@Provides fun provideMyPresenter(): MyPresenter = … Koin factory { MyPresenter() }
ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ 3min Dagger → Koin factory, single, scopeؔΛͬͯείʔϓΛ੍ޚ͢Δ ΞϓϦέʔγϣϯ୯ҐͰڞ௨ͷΠϯελϯεΛ͏ Dagger
@Provides @Singleton fun provideRetrofit( okHttpClient: OkHttpClient ): Retrofit Koin single { Retrofit.Builder()… }
ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ 3min Dagger → Koin factory, single, scopeؔΛͬͯείʔϓΛ੍ޚ͢Δ ΧελϜείʔϓΛఆٛ Dagger
@Scope @Retention(AnnotationRetention.RUNTIME) annotation class ActivityScope @Subcomponent @ActivityScope interface MyActivitySubcomponent { ... } Koin scope(“MyActivity”) { … }
Dagger → Koin 3min ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ ɾநΫϥεΛೖ͍ͨ͠ ɾಉ͡ܕʹผͷΠϯελϯεΛೖ͍ͨ͠ ɾModuleΛ֊Խ͍ͨ͠
ɾ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") { … } }
Dagger → Koin 3min ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ ɾநΫϥεΛೖ͍ͨ͠ ɾಉ͡ܕʹผͷΠϯελϯεΛೖ͍ͨ͠ ɾModuleΛ֊Խ͍ͨ͠
ɾநΫϥεΛೖ͍ͨ͠ 3min Dagger → Koin Dagger @Binds fun bindUserApi( userApiClient:
UserApiClient ): UserApi Koin single { UserApiClient() } bind UserApi::class
Dagger → Koin 3min ɾDIͷείʔϓΛίϯτϩʔϧ͍ͨ͠ ɾநΫϥεΛೖ͍ͨ͠ ɾಉ͡ܕʹผͷΠϯελϯεΛೖ͍ͨ͠ ɾModuleΛ֊Խ͍ͨ͠
ɾಉ͡ܕʹผͷΠϯελϯεΛೖ͍ͨ͠ 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() }
ϝϦοτɾσϝϦοτ 3min
ɾϝϦοτ 3min ϝϦοτɾσϝϦοτ Daggerʹൺͯґଘੑͷهड़ํ๏͕؆ܿͰɺΘ͔Γ͍͢ Field InjectionͷͨΊʹมΛpublicʹ͢Δඞཁ͕ͳ͍ AACͷViewModelͷInjectionʹରԠ͍ͯ͠Δ ίʔυੜΛߦΘͳ͍ͷͰɺίϯύΠϧ࣌ؒॖ͕ݟࠐΊΔ ϚϧνϞδϡʔϧϓϩδΣΫτͷಋೖ͕؆୯
ɾσϝϦοτ 3min ϝϦοτɾσϝϦοτ ґଘੑͷղܾΛίϯύΠϧ࣌ʹ͢ΔDaggerʹൺͯϥϯλΠϜ͕͍ ґଘੑͷॆʹࣦഊͨ͠ͱ͖ʹϥϯλΠϜΤϥʔͰམͪΔ͜ͱ͕͋Δ →ґଘੑͷॆʹ͍ͭͯςετ͕Ͱ͖ΔͨΊɺ൛Ͱى͜Δ֬Լ͛ΒΕΔ https://github.com/Sloy/android-dependency-injection-performance → moduleఆٛʹcreateOnStart=falseΛ͢͜ͱͰΠϯελϯεԽΛԆͰ͖Δ
·ͱΊ 1min
͋Γ͕ͱ͏͍͟͝·ͨ͠ Shibuya.apk #30 https://twitter.com/itometeam https://github.com/itome https://medium.com/@itometeam Cyberagent CATS ௩ຊ ࢤ