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

タップルでたっぷりDaggerを使って マルチモジュール構築している話 :)

Sato Shun
September 10, 2019

タップルでたっぷりDaggerを使って マルチモジュール構築している話 :)

タップルでたっぷりDaggerを使ってマルチモジュール構築している話です!

Sato Shun

September 10, 2019
Tweet

More Decks by Sato Shun

Other Decks in Programming

Transcript

  1. CA.apk #8
    ࠤ౻ ൏ / Sato Shun

    Twitter: @stsn_jp

    GitHub: satoshun
    λοϓϧͰͨͬ΀ΓDaggerΛ࢖ͬͯ
    ϚϧνϞδϡʔϧߏங͍ͯ͠Δ࿩ :)

    View full-size slide

  2. ँࣙ
    • λΠτϧ͸ɺogaclejapan͞ΜͷɺFlux de Relax :) Λࢀ
    ߟʹ͓ͯ͠Γ·͢

    • https://speakerdeck.com/ogaclejapan/flux-de-relax

    View full-size slide

  3. ࠓճ࿩͞ͳ͍͜ͱ
    • Daggerૉ੖Β͍͠Μͩͧʂ͍ͬͯ͏࿩Ͱ͸ͳ͍Ͱ͢

    • Koinͱ͔ଞͷϥΠϒϥϦͳͲͷൺֱͰ͸͋Γ·ͤΜ

    View full-size slide

  4. ࠓճ࿩͢͜ͱ
    • Daggerͷجຊߏ੒

    • ϚϧνϞδϡʔϧͷجຊߏ੒

    • AnalyticsϞδϡʔϧΛྫʹɺϥΠϒϥϦͷ஌ࣝΛϞ
    δϡʔϧʹด͡ࠐΊΔํ๏

    • ֤FeatureϞδϡʔϧͷ࿩

    • RouterϞδϡʔϧͷ࿩

    View full-size slide

  5. Daggerͷجຊߏ੒
    • Android Dagger࢖ͬͯ·͢

    • ͨͩɺແཧͯ͠࢖͏ඞཁͳ͍ͱࢥ͏:D

    • Dynamic Feature Moduleͱ૬ੑѱ͍ʢଟ෼ʣ

    • ViewModelͷαϙʔτ͕ೖͬͨΒϫϯͪΌΜ (ISSUE͸͋Δ)

    • શ෦ɺDagger͔ΒΠϯελϯε࡞Ζ͏ͥʙͬͯײ͡Ͱ͸ͳ
    ͍

    • ࣮͸DaggerΛͨͬ΀Γ࢖ͬͯͳ͍Ͱ͢

    View full-size slide

  6. @Singleton
    @Component(
    modules = [
    AndroidInjectionModule::class,
    FeatureModule::class,
    AnalyticsModule::class
    ]
    )
    interface AppComponent : AndroidInjector {
    ...
    }

    View full-size slide

  7. @Singleton
    @Component(
    modules = [
    AndroidInjectionModule::class,
    FeatureModule::class,
    AnalyticsModule::class
    ]
    )
    interface AppComponent : AndroidInjector {
    ...
    }

    View full-size slide

  8. AnalyticsModule?
    • AnalyticsϞδϡʔϧʹఆٛ͞Ε͍ͯΔDaggerͷModule

    • Google Analytics for Firebaseʹґଘ͍ͯ͠Δ

    • Google Analytics͸ͱͬͬͬͯ΋Ͱ͔͍ϥΠϒϥϦ

    • Google AnalyticsͷҰ෦ͷػೳ͔͠࢖͍ͬͯͳ͍͠ɺ্ख͍͜
    ͱ΍Γ͍ͨ

    View full-size slide

  9. interface Analytics {
    ...
    }
    .

    View full-size slide

  10. interface Analytics {
    ...
    }
    .
    @Singleton
    internal class FirebaseAnalyticsImpl @Inject constructor(
    private val app: Application
    ) : Analytics {
    ...
    }
    .

    View full-size slide

  11. interface Analytics {
    ...
    }
    .
    @Singleton
    internal class FirebaseAnalyticsImpl @Inject constructor(
    private val app: Application
    ) : Analytics {
    ...
    }
    .

    View full-size slide

  12. interface Analytics {
    .
    ...
    }
    .
    @Singleton
    internal class FirebaseAnalyticsImpl @Inject constructor(
    .
    private val app: Application
    ) : Analytics {
    .
    ...
    }
    .

    View full-size slide

  13. interface Analytics {
    .
    ...
    .
    }
    .
    @Singleton
    internal class FirebaseAnalyticsImpl @Inject constructor(
    .
    private val app: Application
    ) : Analytics {
    .
    ...
    .
    }
    .
    @Module
    internal interface AnalyticsBindModule {
    .
    @Binds
    fun bind(impl: FirebaseAnalyticsImpl): Analytics
    }
    .

    View full-size slide

  14. interface Analytics {
    .
    ...
    .
    }
    .
    @Singleton
    internal class FirebaseAnalyticsImpl @Inject constructor(
    .
    private val app: Application
    ) : Analytics {
    .
    ...
    .
    }
    .
    @Module
    internal interface AnalyticsBindModule {
    .
    @Binds
    fun bind(impl: FirebaseAnalyticsImpl): Analytics
    }
    .

    View full-size slide

  15. interface Analytics {
    .
    ...
    .
    }
    .
    @Singleton
    .
    internal class FirebaseAnalyticsImpl @Inject constructor(
    .
    private val app: Application
    ) : Analytics {
    .
    ...
    .
    }
    .
    @Module
    .
    internal interface AnalyticsBindModule {
    ..
    @Binds
    fun bind(impl: FirebaseAnalyticsImpl): Analytics
    }
    ..

    View full-size slide

  16. @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 {
    ..
    ...
    }
    .

    View full-size slide

  17. @Singleton
    @Component(
    modules = [
    AndroidInjectionModule::class,
    FeatureModule::class,
    AnalyticsModule::class
    ]
    )
    interface AppComponent : AndroidInjector {
    ...
    }

    View full-size slide

  18. internal class GachaFragment : Fragment() {
    @Inject lateinit var analytics: FirebaseAnalyticsImpl
    ...
    }
    .

    View full-size slide

  19. internal class GachaFragment : Fragment() {
    @Inject lateinit var analytics: Analytics
    ...
    }
    .

    View full-size slide

  20. AnalyticsModule·ͱΊ
    • αʔυύʔςΟϥΠϒϥϦ͕ڊେ͔ͭɺͦͷ஌ࣝΛग़དྷ
    ΔݶΓด͡ࠐΊ͍ͨͱ͖ʹ༗ޮͳख๏

    • ઐ༻ͷϞδϡʔϧΛ࡞ͬͯ͋͛ͯɺΠϯλϑΣʔεΛఆ
    ٛɻͦͯ͠ɺ࣮૷Λinternalɺ@BindsͰґଘΛఆٛ͢Δ

    • ·ͨϝϯς͞Ε͍ͯͳ͍ɺAPI͕ෳࡶͳࣾ಺ϥΠϒϥϦ
    ʹ΋༗ޮʹ࢖͏͜ͱ͕ग़དྷΔ

    • ϝϯς͞Εͯͳ͍ࣾ಺ϥΠϒϥϦͳΜͯͳ͍ΜͩΑͳ͊

    View full-size slide

  21. ֤FeatureϞδϡʔϧʹ͍ͭͯ
    • ֤FeatureϞδϡʔϧ͝ͱʹઐ༻ͷDaggerͷModuleΛ
    ͍࣋ͬͯΔ

    • gachaϞδϡʔϧ: GachaFeatureModule

    • settingϞδϡʔϧ: SettingFeatureModule

    • …

    View full-size slide

  22. @Module
    interface GachaFeatureModule {
    @ContributesAndroidInjector
    fun contributeGachaActivity(): GachaActivity
    }

    View full-size slide

  23. @Module
    interface GachaFeatureModule {
    @ContributesAndroidInjector
    fun contributeGachaActivity(): GachaActivity
    }
    @Module(
    includes = [
    GachaFeatureModule::class,
    ]
    )
    interface FeatureModule

    View full-size slide

  24. @Module
    interface GachaFeatureModule {
    @ContributesAndroidInjector
    fun contributeGachaActivity(): GachaActivity
    }
    @Module(
    includes = [
    GachaFeatureModule::class,
    SettingFeatureModule::class,
    ]
    )
    interface FeatureModule

    View full-size slide

  25. @Module
    interface GachaFeatureModule {
    @ContributesAndroidInjector
    fun contributeGachaActivity(): GachaActivity
    }
    @Module(
    includes = [
    GachaFeatureModule::class,
    SettingFeatureModule::class,
    ShopFeatureModule::class,
    .
    ]
    )
    interface FeatureModule

    View full-size slide

  26. GachaFeatureModule::class,
    .
    SettingFeatureModule::class,
    .
    ShopFeatureModule::class,
    .
    ]
    .
    )
    .
    interface FeatureModule
    .
    @Singleton
    @Component(
    modules = [
    AndroidInjectionModule::class,
    FeatureModule::class,
    AnalyticsModule::class
    ]
    )
    interface AppComponent : AndroidInjector {
    ...
    }

    View full-size slide

  27. GachaFeatureModule::class,
    .
    SettingFeatureModule::class,
    .
    ShopFeatureModule::class,
    .
    ]
    .
    )
    .
    interface FeatureModule
    .
    @Singleton
    @Component(
    modules = [
    AndroidInjectionModule::class,
    FeatureModule::class,
    AnalyticsModule::class
    ]
    )
    interface AppComponent : AndroidInjector {
    ...
    }

    View full-size slide

  28. FeatureϞδϡʔϧ·ͱΊ
    • FeatureϞδϡʔϧຖʹɺSettingFeatureModuleΈ͍ͨ
    ͳײ͡ͰModuleΛఆٛ͢Δ

    • ଞͷΫϥε͸internalͰఆٛ͢Δ͜ͱͰɺ֎ͷϞδϡʔϧ͔
    ΒͷࢀরΛ࠷খݶʹ͢Δ͜ͱ͕ग़དྷΔ

    • ϞδϡʔϧؒͷґଘΛݮΒ͢͜ͱ͕ग़དྷΔʂ

    View full-size slide

  29. FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ
    • ֤ը໘ʢFeatureʣΛαϒϞδϡʔϧʹ੾Γग़ͨ͜͠ͱ
    Ͱɺ͓ޓ͍͕௚઀ࢀরग़དྷͳ͘ͳΔ

    • େ͖͘3ͭͷํ๏͕͋Δʢଟ෼ʣ

    View full-size slide

  30. FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 1
    • จࣈྻʢϦϑϨΫγϣϯʣͰࢦఆ͢Δํ๏

    • PlaidͰ࢖ΘΕͯΔํ๏

    View full-size slide

  31. object Activities {
    /**
    * AboutActivity
    */
    object About : AddressableActivity {
    override val className = "$PACKAGE_NAME.about.ui.AboutA
    ctivity"
    }
    }

    View full-size slide

  32. FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 2
    • ֤FeatureϞδϡʔϧ಺ʹભҠ༻ͷΠϯλʔϑΣʔεΛ
    ఆٛͯ͠ɺappϞδϡʔϧͰ࣮૷͢Δ

    • Navigation Componentͱͷ૬ੑ΋ྑ͍ʂʂ

    View full-size slide

  33. FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 2
    • ֤FeatureϞδϡʔϧ಺ʹભҠ༻ͷΠϯλʔϑΣʔεΛ
    ఆٛͯ͠ɺappϞδϡʔϧͰ࣮૷͢Δ

    • Navigation Componentͱͷ૬ੑ΋ྑ͍ʂʂ

    View full-size slide

  34. FeatureϞδϡʔϧؒͷભҠʹ͍ͭͯ 3
    • ઐ༻ͷϞδϡʔϧΛ࡞੒ͯ͠ɺ֤ը໘༻ͷΠϯλʔ
    ϑΣʔεΛఆٛ͢Δ

    • λοϓϧͰ͸ͦͷઐ༻ϞδϡʔϧΛRouterͰ࡞੒͍ͯ͠Δ

    • interface GachaDirections

    • interface SettingDirections

    • ֤FeatureϞδϡʔϧͰɺ͜ͷDirectionsΠϯλʔϑΣʔ
    εΛ࢖͍ભҠ͢Δ

    View full-size slide

  35. // ͜Ε͸RouterϞδϡʔϧͰఆٛ
    interface GachaDirections {
    ..
    @CheckResult
    fun createIntent(context: Context): Intent
    }
    .

    View full-size slide

  36. // ͜Ε͸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)
    }
    .
    }
    .

    View full-size slide

  37. }
    .
    // ҎԼɺ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
    }
    .

    View full-size slide

  38. 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

    View full-size slide

  39. @Singleton
    @Component(
    modules = [
    AndroidInjectionModule::class,
    FeatureModule::class,
    AnalyticsModule::class,
    ]
    )
    interface AppComponent : AndroidInjector {
    ...
    }

    View full-size slide

  40. @Module(
    includes = [
    GachaFeatureModule::class,
    ...
    ]
    )
    interface FeatureModule

    View full-size slide

  41. class MainActivity : AppCompatActivity() {
    @Inject lateinit var gachaDirections: GachaDirections
    }

    View full-size slide

  42. ·ͱΊ
    • Google AnalyticsͳͲͷϥΠϒϥϦͷ஌ࣝΛด͡ࠐΊΔͨΊ
    ʹɺϞδϡʔϧΛఆٛ͠ɺDaggerͰґଘΛղܾ͢Δ

    • ϥΠϒϥϦ͕มΘΔՄೳੑ͕ߴ͍৔߹ɺΑΓ༗ޮ

    • ֤ը໘΁ͷભҠ͸ɺΠϯλʔϑΣʔεΛద੾ͳϞδϡʔϧʹ഑
    ஔͯ͠ɺద੾ͳϞδϡʔϧͰ࣮૷͠ɺDaggerͰґଘΛղܾ͢Δ

    • λοϓϧͩͱRouterϞδϡʔϧʹΠϯλʔϑΣʔεΛ഑ஔɺ࣮૷͸
    ֤FeatureϞδϡʔϧͰߦ͍ͬͯΔ

    View full-size slide