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
タップルでたっぷりDaggerを使って マルチモジュール構築している話 :)
Search
Sato Shun
September 10, 2019
Programming
2
2.3k
タップルでたっぷりDaggerを使って マルチモジュール構築している話 :)
タップルでたっぷりDaggerを使ってマルチモジュール構築している話です!
Sato Shun
September 10, 2019
Tweet
Share
More Decks by Sato Shun
See All by Sato Shun
Kotlin Nativeにおけるfrozen状態と並行処理について
satoshun
0
850
DroidKaigi 2020: System UIをコントロールして、 画面を最大限に生かしたアプリを構築する / Build apps that make the best uses of device screens by controlling System UI
satoshun
4
1.7k
Kotlin Fest 2019: Kotlin型実践入門
satoshun
9
6.2k
R8/ProGuard 徹底比較
satoshun
8
3.9k
Android: Introduction Android Support Annotations
satoshun
0
110
Android: Daggear2でDI
satoshun
0
100
Other Decks in Programming
See All in Programming
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
Tauriでネイティブアプリを作りたい
tsucchinoko
0
370
EMになってからチームの成果を最大化するために取り組んだこと/ Maximize team performance as EM
nashiusagi
0
100
Jakarta EE meets AI
ivargrimstad
0
690
カンファレンスの「アレ」Webでなんとかしませんか? / Conference “thing” Why don't you do something about it on the Web?
dero1to
1
110
ふかぼれ!CSSセレクターモジュール / Fukabore! CSS Selectors Module
petamoriken
0
150
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.3k
アジャイルを支えるテストアーキテクチャ設計/Test Architecting for Agile
goyoki
9
3.3k
色々なIaCツールを実際に触って比較してみる
iriikeita
0
330
Functional Event Sourcing using Sekiban
tomohisa
0
100
TypeScriptでライブラリとの依存を限定的にする方法
tutinoko
3
700
Hotwire or React? ~アフタートーク・本編に含めなかった話~ / Hotwire or React? after talk
harunatsujita
1
120
Featured
See All Featured
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
1.9k
Designing Experiences People Love
moore
138
23k
A designer walks into a library…
pauljervisheath
204
24k
Fireside Chat
paigeccino
34
3k
Designing the Hi-DPI Web
ddemaree
280
34k
Ruby is Unlike a Banana
tanoku
97
11k
Making the Leap to Tech Lead
cromwellryan
133
8.9k
GitHub's CSS Performance
jonrohan
1030
460k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
250
21k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
47
2.1k
Reflections from 52 weeks, 52 projects
jeffersonlam
346
20k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Transcript
CA.apk #8 ࠤ౻ ൏ / Sato Shun Twitter: @stsn_jp GitHub:
satoshun λοϓϧͰͨͬΓDaggerΛͬͯ ϚϧνϞδϡʔϧߏங͍ͯ͠Δ :)
ँࣙ • λΠτϧɺogaclejapan͞ΜͷɺFlux de Relax :) Λࢀ ߟʹ͓ͯ͠Γ·͢ • https://speakerdeck.com/ogaclejapan/flux-de-relax
ࠓճ͞ͳ͍͜ͱ • DaggerૉΒ͍͠Μͩͧʂ͍ͬͯ͏Ͱͳ͍Ͱ͢ • Koinͱ͔ଞͷϥΠϒϥϦͳͲͷൺֱͰ͋Γ·ͤΜ
ࠓճ͢͜ͱ • Daggerͷجຊߏ • ϚϧνϞδϡʔϧͷجຊߏ • AnalyticsϞδϡʔϧΛྫʹɺϥΠϒϥϦͷࣝΛϞ δϡʔϧʹด͡ࠐΊΔํ๏ • ֤FeatureϞδϡʔϧͷ
• RouterϞδϡʔϧͷ
Daggerͷجຊߏ • Android Daggerͬͯ·͢ • ͨͩɺແཧͯ͠͏ඞཁͳ͍ͱࢥ͏:D • Dynamic Feature Moduleͱ૬ੑѱ͍ʢଟʣ
• ViewModelͷαϙʔτ͕ೖͬͨΒϫϯͪΌΜ (ISSUE͋Δ) • શ෦ɺDagger͔ΒΠϯελϯε࡞Ζ͏ͥʙͬͯײ͡Ͱͳ ͍ • ࣮DaggerΛͨͬΓͬͯͳ͍Ͱ͢
None
None
None
None
None
@Singleton @Component( modules = [ AndroidInjectionModule::class, FeatureModule::class, AnalyticsModule::class ] )
interface AppComponent : AndroidInjector<App> { ... }
@Singleton @Component( modules = [ AndroidInjectionModule::class, FeatureModule::class, AnalyticsModule::class ] )
interface AppComponent : AndroidInjector<App> { ... }
AnalyticsModule? • AnalyticsϞδϡʔϧʹఆٛ͞Ε͍ͯΔDaggerͷModule • Google Analytics for Firebaseʹґଘ͍ͯ͠Δ • Google
AnalyticsͱͬͬͬͯͰ͔͍ϥΠϒϥϦ • Google AnalyticsͷҰ෦ͷػೳ͔͍ͬͯ͠ͳ͍͠ɺ্ख͍͜ ͱΓ͍ͨ
interface Analytics { ... } .
interface Analytics { ... } . @Singleton internal class FirebaseAnalyticsImpl
@Inject constructor( private val app: Application ) : Analytics { ... } .
interface Analytics { ... } . @Singleton internal class FirebaseAnalyticsImpl
@Inject constructor( private val app: Application ) : Analytics { ... } .
interface Analytics { . ... } . @Singleton internal class
FirebaseAnalyticsImpl @Inject constructor( . private val app: Application ) : Analytics { . ... } .
interface Analytics { . ... . } . @Singleton internal
class FirebaseAnalyticsImpl @Inject constructor( . private val app: Application ) : Analytics { . ... . } . @Module internal interface AnalyticsBindModule { . @Binds fun bind(impl: FirebaseAnalyticsImpl): Analytics } .
interface Analytics { . ... . } . @Singleton internal
class FirebaseAnalyticsImpl @Inject constructor( . private val app: Application ) : Analytics { . ... . } . @Module internal interface AnalyticsBindModule { . @Binds fun bind(impl: FirebaseAnalyticsImpl): Analytics } .
interface Analytics { . ... . } . @Singleton .
internal class FirebaseAnalyticsImpl @Inject constructor( . private val app: Application ) : Analytics { . ... . } . @Module . internal interface AnalyticsBindModule { .. @Binds fun bind(impl: FirebaseAnalyticsImpl): Analytics } ..
@Singleton internal class FirebaseAnalyticsImpl @Inject constructor( . private val app:
Application ) : Analytics { ... . } . @Module . internal interface AnalyticsBindModule { .. @Binds fun bind(impl: FirebaseAnalyticsImpl): Analytics } .. . @Module(includes = [AnalyticsBindModule::class]) .. object AnalyticsModule { .. ... } .
@Singleton @Component( modules = [ AndroidInjectionModule::class, FeatureModule::class, AnalyticsModule::class ] )
interface AppComponent : AndroidInjector<App> { ... }
internal class GachaFragment : Fragment() { @Inject lateinit var analytics:
FirebaseAnalyticsImpl ... } .
internal class GachaFragment : Fragment() { @Inject lateinit var analytics:
Analytics ... } .
AnalyticsModule·ͱΊ • αʔυύʔςΟϥΠϒϥϦ͕ڊେ͔ͭɺͦͷࣝΛग़དྷ ΔݶΓด͡ࠐΊ͍ͨͱ͖ʹ༗ޮͳख๏ • ઐ༻ͷϞδϡʔϧΛ࡞ͬͯ͋͛ͯɺΠϯλϑΣʔεΛఆ ٛɻͦͯ͠ɺ࣮Λinternalɺ@BindsͰґଘΛఆٛ͢Δ • ·ͨϝϯς͞Ε͍ͯͳ͍ɺAPI͕ෳࡶͳࣾϥΠϒϥϦ ʹ༗ޮʹ͏͜ͱ͕ग़དྷΔ
• ϝϯς͞Εͯͳ͍ࣾϥΠϒϥϦͳΜͯͳ͍ΜͩΑͳ͊
֤FeatureϞδϡʔϧʹ͍ͭͯ • ֤FeatureϞδϡʔϧ͝ͱʹઐ༻ͷDaggerͷModuleΛ ͍࣋ͬͯΔ • gachaϞδϡʔϧ: GachaFeatureModule • settingϞδϡʔϧ: SettingFeatureModule
• …
@Module interface GachaFeatureModule { @ContributesAndroidInjector fun contributeGachaActivity(): GachaActivity }
@Module interface GachaFeatureModule { @ContributesAndroidInjector fun contributeGachaActivity(): GachaActivity } @Module(
includes = [ GachaFeatureModule::class, ] ) interface FeatureModule
@Module interface GachaFeatureModule { @ContributesAndroidInjector fun contributeGachaActivity(): GachaActivity } @Module(
includes = [ GachaFeatureModule::class, SettingFeatureModule::class, ] ) interface FeatureModule
@Module interface GachaFeatureModule { @ContributesAndroidInjector fun contributeGachaActivity(): GachaActivity } @Module(
includes = [ GachaFeatureModule::class, SettingFeatureModule::class, ShopFeatureModule::class, . ] ) interface FeatureModule
GachaFeatureModule::class, . SettingFeatureModule::class, . ShopFeatureModule::class, . ] . ) .
interface FeatureModule . @Singleton @Component( modules = [ AndroidInjectionModule::class, FeatureModule::class, AnalyticsModule::class ] ) interface AppComponent : AndroidInjector<App> { ... }
GachaFeatureModule::class, . SettingFeatureModule::class, . ShopFeatureModule::class, . ] . ) .
interface FeatureModule . @Singleton @Component( modules = [ AndroidInjectionModule::class, FeatureModule::class, AnalyticsModule::class ] ) interface AppComponent : AndroidInjector<App> { ... }
FeatureϞδϡʔϧ·ͱΊ • FeatureϞδϡʔϧຖʹɺSettingFeatureModuleΈ͍ͨ ͳײ͡ͰModuleΛఆٛ͢Δ • ଞͷΫϥεinternalͰఆٛ͢Δ͜ͱͰɺ֎ͷϞδϡʔϧ͔ ΒͷࢀরΛ࠷খݶʹ͢Δ͜ͱ͕ग़དྷΔ • ϞδϡʔϧؒͷґଘΛݮΒ͢͜ͱ͕ग़དྷΔʂ
FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ • ֤ը໘ʢFeatureʣΛαϒϞδϡʔϧʹΓग़ͨ͜͠ͱ Ͱɺ͓ޓ͍͕ࢀরग़དྷͳ͘ͳΔ • େ͖͘3ͭͷํ๏͕͋Δʢଟʣ
FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 1 • จࣈྻʢϦϑϨΫγϣϯʣͰࢦఆ͢Δํ๏ • PlaidͰΘΕͯΔํ๏
object Activities { /** * AboutActivity */ object About :
AddressableActivity { override val className = "$PACKAGE_NAME.about.ui.AboutA ctivity" } }
FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 2 • ֤FeatureϞδϡʔϧʹભҠ༻ͷΠϯλʔϑΣʔεΛ ఆٛͯ͠ɺappϞδϡʔϧͰ࣮͢Δ • Navigation Componentͱͷ૬ੑྑ͍ʂʂ
FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 2 • ֤FeatureϞδϡʔϧʹભҠ༻ͷΠϯλʔϑΣʔεΛ ఆٛͯ͠ɺappϞδϡʔϧͰ࣮͢Δ • Navigation Componentͱͷ૬ੑྑ͍ʂʂ
FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 3 • ઐ༻ͷϞδϡʔϧΛ࡞ͯ͠ɺ֤ը໘༻ͷΠϯλʔ ϑΣʔεΛఆٛ͢Δ • λοϓϧͰͦͷઐ༻ϞδϡʔϧΛRouterͰ࡞͍ͯ͠Δ • interface GachaDirections
• interface SettingDirections • ֤FeatureϞδϡʔϧͰɺ͜ͷDirectionsΠϯλʔϑΣʔ εΛ͍ભҠ͢Δ
// ͜ΕRouterϞδϡʔϧͰఆٛ interface GachaDirections { .. @CheckResult fun createIntent(context: Context):
Intent } .
// ͜ΕRouterϞδϡʔϧͰఆٛ interface GachaDirections { .. @CheckResult fun createIntent(context: Context):
Intent } . // ҎԼɺGachaϞδϡʔϧ internal class GachaDirectionsImpl @Inject constructor() : GachaDirections { . override fun createIntent(context: Context): Intent { . return GachaActivity.createIntent(context) } . } .
} . // ҎԼɺGachaϞδϡʔϧ internal class GachaDirectionsImpl @Inject constructor() :
GachaDirections { . override fun createIntent(context: Context): Intent { . return GachaActivity.createIntent(context) } . } . @Module internal interface GachaBindsModule { . @Binds fun bindGachaDirections(directions: GachaDirectionsImpl): GachaDirections } .
override fun createIntent(context: Context): Intent { . return GachaActivity.createIntent(context) }
. } . @Module internal interface GachaBindsModule { . @Binds fun bindGachaDirections(directions: GachaDirectionsImpl): GachaDirections } . @Module( includes = [ GachaBindsModule::class ] ) interface GachaFeatureModule
@Singleton @Component( modules = [ AndroidInjectionModule::class, FeatureModule::class, AnalyticsModule::class, ] )
interface AppComponent : AndroidInjector<App> { ... }
@Module( includes = [ GachaFeatureModule::class, ... ] ) interface FeatureModule
class MainActivity : AppCompatActivity() { @Inject lateinit var gachaDirections: GachaDirections
}
None
·ͱΊ • Google AnalyticsͳͲͷϥΠϒϥϦͷࣝΛด͡ࠐΊΔͨΊ ʹɺϞδϡʔϧΛఆٛ͠ɺDaggerͰґଘΛղܾ͢Δ • ϥΠϒϥϦ͕มΘΔՄೳੑ͕ߴ͍߹ɺΑΓ༗ޮ • ֤ը໘ͷભҠɺΠϯλʔϑΣʔεΛదͳϞδϡʔϧʹ ஔͯ͠ɺదͳϞδϡʔϧͰ࣮͠ɺDaggerͰґଘΛղܾ͢Δ
• λοϓϧͩͱRouterϞδϡʔϧʹΠϯλʔϑΣʔεΛஔɺ࣮ ֤FeatureϞδϡʔϧͰߦ͍ͬͯΔ