Speaker Deck
Speaker Deck Pro
Sign in
Sign up
for free
タップルでたっぷりDaggerを使って マルチモジュール構築している話 :)
Sato Shun
September 10, 2019
Programming
2
1.5k
タップルでたっぷりDaggerを使って マルチモジュール構築している話 :)
タップルでたっぷりDaggerを使ってマルチモジュール構築している話です!
Sato Shun
September 10, 2019
Tweet
Share
More Decks by Sato Shun
See All by Sato Shun
satoshun
4
960
satoshun
8
4.4k
satoshun
7
2.4k
satoshun
0
52
satoshun
0
55
Other Decks in Programming
See All in Programming
hirotokirimaru
1
390
loleg
0
190
shin1x1
0
580
cwozaki
1
1.6k
ajstarks
2
550
masayaaoyama
4
520
77web
0
200
kazuki19992
0
440
aratayokoyama
0
180
asumikan
0
280
akatsukinewgrad
0
130
cocoeyes02
0
220
Featured
See All Featured
chriscoyier
684
180k
zenorocha
297
39k
sferik
609
54k
jakevdp
774
200k
zakiwarfel
88
3.3k
bkeepers
52
4.1k
michaelherold
225
8.4k
lara
16
2.6k
smashingmag
229
18k
trishagee
20
2k
scottboms
251
11k
keavy
106
14k
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ϞδϡʔϧͰߦ͍ͬͯΔ