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

Dagger Hilt로 의존성 주입부터 멀티모듈화까지

Sungyong An
September 12, 2023

Dagger Hilt로 의존성 주입부터 멀티모듈화까지

2023년 9월 12일 (화) 드로이드나이츠 2023 행사에서의 발표자료입니다.
https://festa.io/events/3635

Sungyong An

September 12, 2023
Tweet

More Decks by Sungyong An

Other Decks in Programming

Transcript

  1. Dagger Hilt۽


    ੄ઓࢿ ઱ੑࠗఠ ݣ౭ݽٕചө૑
    SUNGYONG AN / NAVER WEBTOON

    View Slide

  2. Sungyong An

    NAVER WEBTOON

    Android GDE

    @fornewid
    Link: h
    tt
    ps://github.com/fornewid

    View Slide

  3. “যڃ ղਊਸ ׮ܖաਃ?”
    🤔
    Intro

    View Slide

  4. Dependency Injection
    ੄ઓࢿ ઱ੑ(DI)਷ ೞա੄ ё୓о ׮ܲ ё୓੄ ੄ઓࢿਸ ઁҕೞח ӝߨ੉׮.

    ੄ઓࢿ ઱ੑ੄ ੄بח ё୓੄ ࢤࢿҗ ࢎਊ੄ ҙबਸ ܻ࠙ೞח Ѫ੉׮.

    DI ਗ஗ਸ ٮܰݶ ഴܯೠ জ ইఃఫ୊ܳ ਤೠ ష؀ܳ ݃۲ೡ ࣻ ੓׮.

    • ௏٘ ੤ࢎਊ оמ

    • ܻಂష݂ ಞ੄ࢿ

    • పझ౟ ಞ੄ࢿ
    Link: h
    tt
    ps://en.wikipedia.org/wiki/Dependency_injection

    View Slide

  5. // Without Dependency Injection


    class Car {


    private val engine: Engine = Engine() // construct + use


    fun start() {


    engine.start()


    }


    }


    fun main(args: Array) {


    val car = Car()


    car.start()


    }
    Car
    Engine

    View Slide

  6. // Dependency Injection (Constructor Injection)


    class Car(


    private val engine: Engine // use


    ) {


    fun start() {


    engine.start()


    }


    }


    fun main(args: Array) {


    val engine = Engine() // construct


    val car = Car(engine)


    car.start()


    }
    Car
    Engine

    View Slide

  7. // Dependency Injection (Field Injection)


    class Car {


    lateinit var engine: Engine // use


    fun start() {


    engine.start()


    }


    }


    fun main(args: Array) {


    val car = Car()


    car.engine = Engine() // construct


    car.start()


    }
    Car
    Engine

    View Slide

  8. Dagger Hilt
    Androidীࢲ ੄ઓࢿਸ ઱ੑೞח ݾ੸ਵ۽ ӂ੢ೞח ۄ੉࠳۞ܻ.

    ೐۽ં౟੄ ݽٚ Android ௿ېझী ஶప੉ցܳ ઁҕೞҊ, ࣻݺ ઱ӝܳ ੗زਵ۽ ҙܻ೧ળ׮.

    (Application, Activity, Service, BroadcastReceiver, ViewModel)

    Hiltח Dagger ӝ߈ ۄ੉࠳۞ܻ۽, ஹ౵ੌ ఋ੐ী ੄ઓࢿ Ӓې೐ܳ Ѩૐೡ ࣻ ੓׮.

    ੌࠗ Jetpack ௿ېझীب ੄ઓࢿਸ ઱ੑೡ ࣻ ੓ب۾, Hilt ഛ੢ ۄ੉࠳۞ܻب ઁҕػ׮.

    (WorkManager, Navigation)
    Link: h
    tt
    ps://developer.android.com/training/dependency-injection#hilt

    View Slide

  9. @Module


    @InstallIn(SingletonComponent::class)


    class EngineModule {


    @Provides // construct


    fun providesEngine(): Engine = Engine()


    }
    Link: h
    tt
    ps://dagger.dev/hilt/quick-sta
    r
    @Provides ١ਸ ੉ਊೞৈ, ੄ઓࢿਸ ઁҕೡ ࣻ ੓׮.
    Engine

    View Slide

  10. @Module


    @InstallIn(SingletonComponent::class)


    class EngineModule {


    @Provides // construct


    fun providesEngine(): Engine = Engine()


    }


    // Dependency Injection (Constructor Injection)


    class Car @Inject constructor( // use


    private val engine: Engine,


    )
    Link: h
    tt
    ps://dagger.dev/hilt/quick-sta
    r
    @Injectܳ ੉ਊೞৈ, ੄ઓࢿਸ ௿ېझ ࢤࢿ੗ী ઱ੑೡ ࣻ ੓׮.
    Car
    Engine

    View Slide

  11. @Module


    @InstallIn(SingletonComponent::class)


    class EngineModule {


    @Provides // construct


    fun providesEngine(): Engine = Engine()


    }


    // Dependency Injection (Constructor Injection)


    class Car @Inject constructor( // use


    private val engine: Engine,


    )


    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    // Dependency Injection (Field Injection)


    @Inject // use


    lateinit var car: Car


    }
    Link: h
    tt
    ps://dagger.dev/hilt/quick-sta
    r
    Android ௿ېझח ࢤࢿ੗о ইצ, ೙٘ী ੄ઓࢿਸ ઱ੑೠ׮.
    Car
    ExampleActivity
    Engine

    View Slide

  12. @Module


    @InstallIn(SingletonComponent::class)


    class EngineModule {


    @Provides


    fun providesEngine(): Engine = Engine()


    }


    // Dependency Injection (Constructor Injection)


    class Car @Inject constructor(


    private val engine: Engine,


    )


    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    // Dependency Injection (Field Injection)


    @Inject


    lateinit var car: Car


    }
    = public @interface Module { ... }


    = public @interface InstallIn { ... }


    = public @interface Provides {}


    = public @interface Inject {}


    = public @interface AndroidEntryPoint { ... }


    = public @interface Inject {}
    Link: h
    tt
    ps://en.wikipedia.org/wiki/Java_annotation
    Ӓؘ۠ Annotationਸ ࢓ಝࠁݶ, ੄ઓࢿ ઱ੑҗ ҙ۲ػ ௏٘о হ׮???

    View Slide

  13. // build.gradle


    dependencies {


    implementation 'com.google.dagger:hilt-android:2.48'


    // For Java


    annotationProcessor ‘com.google.dagger:hilt-compiler:2.48'


    // For Kotlin


    kapt 'com.google.dagger:hilt-compiler:2.48'


    // or


    ksp 'com.google.dagger:hilt-compiler:2.48'


    }
    Link: h
    tt
    ps://dagger.dev/hilt/gradle-setup
    ⚠ KSPח Dagger Hilt 2.48 ߡ੹ࠗఠ ૑ਗؾפ׮! (alpha)
    Hiltо Annotationਸ ӝ߈ਵ۽, ੄ઓࢿ ઱ੑী ೙ਃೠ ௏٘ܳ ٜ݅যળ׮.
    There is no magic!

    View Slide

  14. “Dagger Hiltо ࢤࢿೞח ௏٘ܳ ࠙ࢳೞৈ,

    Hiltо উ٘۽੉٘ জী ੄ઓࢿਸ ઱ੑೞח җ੿ਸ ੉೧೧ ࠁ੗.”
    Goal
    + “ݣ౭ ݽٕীࢲ੄ ࢎਊ ߑߨਸ Ҋ޹೧ ࠁ੗.”
    ⚠ ठۄ੉٘੄ ௏٘ח Dagger Hilt 2.48 ߡ੹ਸ ӝળਵ۽ ੘ࢿغ঻णפ׮.

    View Slide

  15. Dagger Hilt ղࠗ௏٘ ࠙ࢳ.

    View Slide

  16. Start!
    @HiltAndroidApp


    class ExampleApplication : Application() {


    @Inject lateinit var bar: Bar


    }


    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject lateinit var bar: Bar


    }


    @Module


    @InstallIn(SingletonComponent::class)


    internal object FooModule {


    @Provides


    fun provideBar(): Bar = Bar()


    }
    Link: h
    tt
    ps://dagger.dev/hilt/quick-sta
    r
    ExampleApplication_HiltComponents.java


    -> Hilt_ExampleApplication.java


    ExampleApplication_GeneratedInjector.java


    ExampleApplication_MembersInjector.java


    -> Hilt_ExampleActivity.java


    ExampleActivity_GeneratedInjector.java


    ExampleActivity_MembersInjector.java


    -> HiltWrapper_FooModule.java


    FooModule_ProvideBarFactory.java
    জ ݽٕ੄ build ಫ؊ী Java ౵ੌٜ੉ ࢤࢿػ׮.

    View Slide

  17. Start!
    @HiltAndroidApp


    class ExampleApplication : Application() {


    @Inject lateinit var bar: Bar


    }


    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject lateinit var bar: Bar


    }


    @Module


    @InstallIn(SingletonComponent::class)


    internal object FooModule {


    @Provides


    fun provideBar(): Bar = Bar()


    }
    Link: h
    tt
    ps://dagger.dev/hilt/quick-sta
    r
    ExampleApplication_HiltComponents.java


    -> Hilt_ExampleApplication.java


    ExampleApplication_GeneratedInjector.java


    ExampleApplication_MembersInjector.java


    -> Hilt_ExampleActivity.java


    ExampleActivity_GeneratedInjector.java


    ExampleActivity_MembersInjector.java


    -> HiltWrapper_FooModule.java


    FooModule_ProvideBarFactory.java
    ӏ஗੉ ࠁ੉աਃ?

    View Slide

  18. public final class ExampleApplication_HiltComponents {


    @Component(modules = { ActivityRetainedCBuilderModule.class, ... })


    @Singleton


    public abstract static class SingletonC implements ...,


    SingletonComponent, ExampleApplication_GeneratedInjector {


    }


    @Subcomponent(modules = { ActivityCBuilderModule.class, ... })


    @ActivityRetainedScoped


    public abstract static class ActivityRetainedC implements ..., ActivityRetainedComponent {


    @Subcomponent.Builder


    abstract interface Builder extends ActivityRetainedComponentBuilder {}


    }


    @Subcomponent(modules = { FragmentCBuilderModule.class, ... })


    @ActivityScoped


    public abstract static class ActivityC implements ...,


    ActivityComponent, ExampleActivity_GeneratedInjector {


    @Subcomponent.Builder


    abstract interface Builder extends ActivityComponentBuilder {}


    }


    ...


    }
    ࢤࢿػ ௏٘ীب ৈ੹൤ Annotation੉ ੓׮???

    View Slide

  19. Component generation
    Link: h
    tt
    ps://medium.com/androiddevelopers/mad-skills-series-hilt-under-the-hood-9d89ee227059
    Hiltо Dagger ௏٘ܳ ࢤࢿೞҊ աࢲ, Daggerо ୭ઙ ௏٘ܳ ࢤࢿೠ׮.

    View Slide

  20. @HiltAndroidApp


    class ExampleApplication : Application()


    // --------------------------------------------------------------------------------


    // Generated by Hilt


    public final class ExampleApplication_HiltComponents {


    @Component(modules = { ActivityRetainedCBuilderModule.class, ... })


    @Singleton


    public abstract static class SingletonC implements SingletonComponent {


    }


    ...


    }


    // --------------------------------------------------------------------------------


    // Generated by Dagger


    public final class DaggerExampleApplication_HiltComponents_SingletonC {


    private static final class SingletonCImpl


    extends ExampleApplication_HiltComponents.SingletonC {


    public void injectExampleApplication(ExampleApplication exampleApplication) {}


    }


    ...


    }
    @HiltAndroidApp਷ জ੄ ੄ઓࢿ Ӓې೐ܳ ࢤࢿೞח ӝળ੉ ػ׮.

    View Slide

  21. Bar
    Overview
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity
    FooModule

    View Slide

  22. @HiltAndroidApp


    class ExampleApplication : Application() {


    @Inject lateinit var bar: Bar


    }
    Bar
    Overview
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity
    FooModule
    (1) ӝࠄ ࢤࢿغח ੄ઓࢿ Ӓې೐ܳ ࢓ಝࠁ੗.

    View Slide

  23. Component hierarchy
    SingletonComponent
    FragmentComponent
    ViewWithFragmentComponent
    ViewComponent
    ActivityRetainedComponent
    ActivityComponent
    ServiceComponent
    ViewModelComponent
    @Singleton
    @ActivityRetainedScoped
    @ServiceScoped
    @ViewModelScoped
    @FragmentScoped
    @ActivityScoped
    @ViewScoped
    @ViewScoped
    Link: h
    tt
    ps://developer.android.com/training/dependency-injection/hilt-android#component-hierarchy
    Hiltо ӝࠄ ઁҕೞח Component৬ Scope.

    View Slide

  24. @Scope


    @Documented


    @Retention(RUNTIME)


    public @interface Singleton {}


    @Singleton


    @DefineComponent


    public interface SingletonComponent {}


    View Slide

  25. public final class ExampleApplication_HiltComponents {


    @Component(


    modules = {


    ApplicationContextModule.class,


    ActivityRetainedCBuilderModule.class,


    }


    )


    @Singleton


    public abstract static class SingletonC implements


    HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,


    SingletonComponent,


    GeneratedComponent {


    }


    }

    View Slide

  26. public final class DaggerExampleApplication_HiltComponents_SingletonC {


    public static Builder builder() {


    return new Builder();


    }


    public static final class Builder {


    public ExampleApplication_HiltComponents.SingletonC build() {


    return new SingletonCImpl();


    }


    }


    private static final class SingletonCImpl extends SingletonC {


    private final SingletonCImpl singletonCImpl = this;


    private SingletonCImpl() {


    }


    }


    }
    п Component݃׮ ੉۠ ௿ېझо ࢤࢿػ׮.

    View Slide

  27. HiltComponents
    SingletonC(Impl)
    FragmentC(Impl)
    ViewWithFragmentC(Impl)
    ViewC(Impl)
    ActivityRetainedC(Impl)
    ActivityC(Impl)
    ServiceC(Impl)
    ViewModelC(Impl)
    @Singleton
    @ActivityRetainedScoped
    @ServiceScoped
    @ViewModelScoped
    @FragmentScoped
    @ActivityScoped
    @ViewScoped
    @ViewScoped
    п Component / Scopeী ؀਽ೞח ௿ېझ.

    View Slide

  28. Component hierarchy
    SingletonComponent
    FragmentComponent
    ViewWithFragmentComponent
    ViewComponent
    ActivityRetainedComponent
    ActivityComponent
    ServiceComponent
    ViewModelComponent
    Link: h
    tt
    ps://developer.android.com/training/dependency-injection/hilt-android#component-hierarchy
    @Inject
    ࢚ਤ ஹನք౟੄ ੄ઓࢿਸ ೞਤী ઱ੑೡ ࣻ ੓Ҋ, ৉ਵ۽ח ೡ ࣻ হ׮. যڌѱ???

    View Slide

  29. DaggerExampleApplication_HiltComponents_SingletonC
    ExampleApplication_HiltComponents
    HiltComponents
    SingletonC
    ActivityRetainedC
    ActivityC
    SingletonCImpl
    ActivityCImpl
    @Singleton
    @ActivityRetainedScoped
    @ActivityScoped
    @Module
    @Module
    ActivityRetainedCImpl

    View Slide

  30. public final class DaggerExampleApplication_HiltComponents_SingletonC {


    private static final class SingletonCImpl extends SingletonC {


    private SingletonCImpl() {}


    }


    private static final class ActivityRetainedCImpl extends ActivityRetainedC {


    private ActivityRetainedCImpl(


    SingletonCImpl singletonCImpl


    ) { ... }


    }


    }

    View Slide

  31. public final class DaggerExampleApplication_HiltComponents_SingletonC {


    private static final class SingletonCImpl extends SingletonC {


    private SingletonCImpl() {}


    }


    private static final class ActivityRetainedCImpl extends ActivityRetainedC {


    private ActivityRetainedCImpl(


    SingletonCImpl singletonCImpl


    ) { ... }


    }


    private static final class ActivityCImpl extends ActivityC {


    private ActivityCImpl(


    SingletonCImpl singletonCImpl,


    ActivityRetainedCImpl activityRetainedCImpl,


    Activity activityParam


    ) { ... }


    }


    }
    ೞਤ ஹನք౟ח ࢚ਤ ஹನք౟ী ૒੽ ੽Ӕೡ ࣻ ੓׮. ߈؀۽ח X.

    View Slide

  32. @Module


    @InstallIn(SingletonComponent::class)


    object FooModule {


    @Provides


    fun provideBar(): Bar = Bar()


    }
    Bar
    Overview
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity
    (2) ૒੽ ੿੄ೠ ੄ઓࢿ੉ Ӓې೐ী যڌѱ ୶оغח૑ ࢓ಝࠁ੗.
    FooModule

    View Slide

  33. @Module


    @InstallIn(SingletonComponent::class)


    object FooModule {


    @Provides


    fun provideBar(): Bar = Bar()


    }


    // --------------------------------------------------------------------------------


    public final class ExampleApplication_HiltComponents {


    @Component(


    modules = {


    ApplicationContextModule.class,


    ActivityRetainedCBuilderModule.class,


    FooModule.class,


    }


    )


    @Singleton


    public abstract static class SingletonC implements


    HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,


    SingletonComponent,


    GeneratedComponent {


    }


    }
    ࢶ঱ೠ Componentী Module੉ ୶оػ׮.

    View Slide

  34. @Module


    @InstallIn(SingletonComponent::class)


    object FooModule {


    @Provides


    fun provideBar(): Bar = Bar()


    }


    // --------------------------------------------------------------------------------


    public final class FooModule_ProvideBarFactory implements Factory {


    public static Bar provideBar() {


    return Preconditions.checkNotNullFromProvides(FooModule.INSTANCE.provideBar());


    }


    }
    @Provides݃׮ ੄ઓࢿਸ ઁҕೞח Factory ௿ېझо ࢤࢿػ׮.

    View Slide

  35. @HiltAndroidApp


    class ExampleApplication : Application() {


    @Inject


    lateinit var bar: Bar


    }
    Bar
    Overview
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity
    FooModule
    (3) উ٘۽੉٘ ௿ېझী ઱ੑೞח җ੿ਸ ࢓ಝࠁ੗.
    Hilt_ExampleApplication.java


    ExampleApplication_GeneratedInjector.java


    ExampleApplication_MembersInjector.java

    View Slide

  36. ExampleApplication_GeneratedInjector.java
    @GeneratedEntryPoint


    @InstallIn(SingletonComponent.class)


    public interface ExampleApplication_GeneratedInjector {


    void injectExampleApplication(ExampleApplication exampleApplication);


    }


    // --------------------------------------------------------------------------------


    public final class ExampleApplication_HiltComponents {


    @Component(modules = { ... })


    @Singleton


    public abstract static class SingletonC implements


    HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,


    SingletonComponent,


    GeneratedComponent,


    ExampleApplication_GeneratedInjector {


    }


    }


    // --------------------------------------------------------------------------------


    public final class DaggerExampleApplication_HiltComponents_SingletonC {


    private static final class SingletonCImpl extends SingletonC {


    public void injectExampleApplication(ExampleApplication instance) {


    }


    }

    View Slide

  37. ExampleApplication_MembersInjector.java
    @HiltAndroidApp


    class ExampleApplication : Application() {


    @Inject lateinit var bar: Bar


    }


    // --------------------------------------------------------------------------------


    public final class ExampleApplication_MembersInjector


    implements MembersInjector {


    public static void injectBar(ExampleApplication instance, Bar bar) {


    instance.bar = bar;


    }


    }


    // --------------------------------------------------------------------------------


    public final class DaggerExampleApplication_HiltComponents_SingletonC {


    private static final class SingletonCImpl extends SingletonC {


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(


    instance, FooModule_ProvideBarFactory.provideBar());


    }


    }
    ࢤࢿػ Injector ௿ېझח Componentী ੸੺൤ ୶оػ׮.

    View Slide

  38. Hilt_ExampleApplication.java
    @HiltAndroidApp


    class ExampleApplication : Application() {


    @Inject lateinit var bar: Bar


    }


    =


    @HiltAndroidApp


    class ExampleApplication : Hilt_ExampleApplication() {


    @Inject lateinit var bar: Bar


    }
    ߄੉౟௏٘ܳ ߸ജೞৈ, ࠗݽ ௿ېझܳ ߸҃ೠ׮.

    View Slide

  39. public abstract class Hilt_ExampleApplication extends Application {


    private boolean injected = false;


    @CallSuper


    @Override


    public void onCreate() {


    if (!injected) {


    injected = true;


    ((ExampleApplication_GeneratedInjector) componentManager.generatedComponent())


    .injectExampleApplication(this);


    }


    super.onCreate();


    }


    private final ApplicationComponentManager componentManager = new ApplicationComponentManager(


    () -> DaggerExampleApplication_HiltComponents_SingletonC.builder()


    .applicationContextModule(new ApplicationContextModule(Hilt_ExampleApplication.this))


    .build());


    }
    Injector۽ SingletonCী ੽Ӕೞৈ, ੄ઓࢿ ઱ੑਸ ਃ୒ೠ׮.

    View Slide

  40. DaggerExampleApplication_HiltComponents_SingletonC
    SingletonCImpl
    Dependency injection flow (Application)
    FooModule_ProvideBarFactory
    ExampleApplication_MemeberInjector
    ExampleApplication
    Hilt_ExampleApplication
    Bar
    ExampleApplication_GeneratedInjector
    ApplicationComponentManager
    ੉۠ ൒ܴਵ۽ ੄ઓࢿ੉ ઱ੑػ׮.

    View Slide

  41. DaggerExampleApplication_HiltComponents_SingletonC
    -CImpl
    Dependency injection flow (Android Classes)
    FooModule_ProvideBarFactory
    {CLASS}_MemeberInjector
    {CLASS}
    Hilt_{CLASS}
    Bar
    {CLASS}_GeneratedInjector
    -ComponentManager
    ׮ܲ Android Classesب زੌೞ׮.

    View Slide

  42. DaggerExampleApplication_HiltComponents_SingletonC
    -CImpl
    Dependency injection flow
    {CLASS}_MemeberInjector
    {CLASS}
    Hilt_{CLASS}
    Bar
    {CLASS}_GeneratedInjector
    -ComponentManager
    ੄ઓࢿਸ ઁҕೞח ࠗ࠙ਸ ખ ؊ ࢓ಝࠁ੗.
    FooModule_ProvideBarFactory

    View Slide

  43. @Module


    @InstallIn(SingletonComponent::class)


    object FooModule {


    @Provides


    fun provideBar(): Bar = Bar()


    }
    @Provides
    Bar
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity
    FooModule_ProvideBarFactory

    View Slide

  44. @Module


    @InstallIn(SingletonComponent::class)


    object FooModule {


    @Provides


    fun provideBar(): Bar = Bar()


    }


    // --------------------------------------------------------------------------------


    public final class FooModule_ProvideBarFactory implements Factory {


    public static Bar provideBar() {


    return Preconditions.checkNotNullFromProvides(FooModule.INSTANCE.provideBar());


    }


    }


    // --------------------------------------------------------------------------------


    private static final class SingletonCImpl extends SingletonC {


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(


    instance, FooModule_ProvideBarFactory.provideBar());


    }


    } @Providesח Factory ௿ېझܳ ా೧ ੄ઓࢿਸ ઁҕೠ׮.

    View Slide

  45. class Bar @Inject constructor()
    @Inject
    Bar
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity

    View Slide

  46. class Bar @Inject constructor()


    // --------------------------------------------------------------------------------


    private static final class SingletonCImpl extends SingletonC {


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(instance, new Bar());


    }


    }
    @Injectח ߹ب੄ ௏٘হ੉, ੄ઓࢿਸ ߄۽ ઁҕೠ׮.

    View Slide

  47. interface Bar


    class BarImpl @Inject constructor(): Bar


    @Module


    @InstallIn(SingletonComponent::class)


    interface FooModule {


    @Binds


    fun bindBar(impl: BarImpl): Bar


    }
    @Binds
    BarImpl
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity

    View Slide

  48. interface Bar


    class BarImpl @Inject constructor(): Bar


    @Module


    @InstallIn(SingletonComponent::class)


    interface FooModule {


    @Binds


    fun bindBar(impl: BarImpl): Bar


    }


    // --------------------------------------------------------------------------------


    private static final class SingletonCImpl extends SingletonC {


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(instance, new BarImpl());


    }


    }
    @Bindsܳ ೣԋ ࢎਊ೧ب زੌೞ׮.

    View Slide

  49. @Singleton


    class Bar @Inject constructor()
    Scope
    Bar
    ExampleApplication
    DaggerExampleApplication_HiltComponents_SingletonC
    ExampleActivity
    DoubleCheck + SwitchingProvider

    View Slide

  50. @Singleton


    class Bar @Inject constructor()


    // --------------------------------------------------------------------------------


    private static final class SingletonCImpl extends SingletonC {


    private Provider barProvider;


    private SingletonCImpl() {


    this.barProvider = DoubleCheck.provider(new SwitchingProvider(this, 0));


    }


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(instance, (Bar)this.barProvider.get());


    }


    private static final class SwitchingProvider implements Provider {


    public T get() {


    switch (this.id) {


    case 0: return new Bar();


    default: throw new AssertionError(this.id);


    }


    }


    }


    } Scopeܳ ࢶ঱ೞݶ, ೧׼ Componentী Providerܳ ࢤࢿೠ׮.

    View Slide

  51. public final class DoubleCheck implements Provider, Lazy {


    public T get() {


    Object result = instance;


    if (result == UNINITIALIZED) {


    synchronized (this) {


    result = instance;


    if (result == UNINITIALIZED) {


    result = provider.get();


    instance = reentrantCheck(instance, result);


    provider = null;


    }


    }


    }


    return (T) result;


    }


    public static , T> Provider provider(P delegate) {


    return new DoubleCheck(delegate);


    }


    }
    DoubleCheckח ё୓ܳ ೞա݅ ࢤࢿೠ׮.

    View Slide

  52. Scope: Advanced
    private static final class SingletonCImpl extends SingletonC {


    private Provider barImplProvider = new SwitchingProvider(this, 0);


    private Provider bindBarProvider = DoubleCheck.provider(this.barImplProvider);


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(instance, (Bar)this.bindBarProvider.get());


    }


    }
    interface Bar


    class BarImpl @Inject constructor(): Bar
    Scopeܳ ࢶ঱ೠ ਤ஖ী DoubleCheckо ࠢח׮.
    @Module


    @InstallIn(SingletonComponent::class)


    interface FooModule {


    @Singleton


    @Binds fun bindBar(impl: BarImpl): Bar


    }

    View Slide

  53. Scope: Advanced
    private static final class SingletonCImpl extends SingletonC {


    private Provider barImplProvider = new SwitchingProvider(this, 0);


    private Provider bindBarProvider = DoubleCheck.provider(this.barImplProvider);


    private Provider bindBar2Provider = DoubleCheck.provider(this.barImplProvider);


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(instance, (Bar)this.bindBarProvider.get());


    ExampleApplication_MembersInjector.injectBar2(instance, (Bar2)this.bindBar2Provider.get());


    }


    }
    interface Bar


    interface Bar2


    class BarImpl @Inject constructor(): Bar, Bar2
    interface FooModule {


    @Singleton


    @Binds fun bindBar(impl: BarImpl): Bar


    @Singleton


    @Binds fun bindBar2(impl: BarImpl): Bar2


    }
    ૊, BarImpl੉ ৈ۞ ߣ ࢤࢿؼ ࣻب ੓׮.

    View Slide

  54. Scope: Advanced
    private static final class SingletonCImpl extends SingletonC {


    private Provider barImplProvider = DoubleCheck.provider(new SwitchingProvider(this, 0));


    public void injectExampleApplication(ExampleApplication instance) {


    ExampleApplication_MembersInjector.injectBar(instance, (Bar)this.barImplProvider.get());


    ExampleApplication_MembersInjector.injectBar2(instance, (Bar2)this.barImplProvider.get());


    }


    }
    interface Bar


    interface Bar2


    @Singleton


    class BarImpl @Inject constructor(): Bar
    @Module


    @InstallIn(SingletonComponent::class)


    interface FooModule {


    @Binds fun bindBar(impl: BarImpl): Bar


    @Binds fun bindBar2(impl: BarImpl): Bar2


    }
    Scopeܳ ࢶ঱ೞח ਤ஖ܳ ઱੄ೞ੗!

    View Slide

  55. DaggerExampleApplication_HiltComponents_SingletonC
    -CImpl
    Dependency injection flow
    FooModule_ProvideBarFactory
    {CLASS}_MemeberInjector
    {CLASS} Bar
    ੄ઓࢿਸ ઱ੑ߉ח ࠗ࠙ਸ ખ ؊ ࢓ಝࠁ੗.
    Hilt_{CLASS}
    -ComponentManager
    {CLASS}_GeneratedInjector

    View Slide

  56. @Inject
    private static final class ActivityCImpl extends SingletonC {


    public void injectExampleActivity(ExampleActivity instance) {


    ExampleActivity_MembersInjector.injectBar(instance, new Bar());


    }


    }
    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject


    lateinit var bar: Bar


    }

    View Slide

  57. @Inject: Inheritance
    private static final class ActivityCImpl extends SingletonC {


    public void injectExampleActivity(ExampleActivity instance) {


    BaseActivity_MembersInjector.injectBar(instance, new Bar());


    ExampleActivity_MembersInjector.injectBar(instance, new Bar());


    }


    }
    @AndroidEntryPoint


    class ExampleActivity : BaseActivity() {


    @Inject


    lateinit var bar: Bar


    }
    public abstract class BaseActivity


    extends ComponentActivity {


    @Inject Bar bar;


    }
    @Inject ݃׮ ࢲ۽ ׮ܲ ё୓ܳ ࢤࢿೠ׮.

    View Slide

  58. Provider
    private static final class ActivityCImpl extends ActivityC {


    private Provider barProvider = new SwitchingProvider(..., 0);


    public void injectExampleActivity(ExampleActivity instance) {


    ExampleActivity_MembersInjector.injectBar(instance, this.barProvider);


    }


    }
    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject


    lateinit var bar: Provider


    }
    get()ਸ ഐ୹ೡ ٸ݃׮, ࢤࢿೠ׮.
    fun doSomething() {


    bar.get().doSomething()


    }

    View Slide

  59. Lazy
    private static final class ActivityCImpl extends ActivityC {


    private Provider barProvider = new SwitchingProvider(..., 0);


    public void injectExampleActivity(ExampleActivity instance) {


    ExampleActivity_MembersInjector.injectBar(instance, DoubleCheck.lazy(this.barProvider));


    }


    }
    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject


    lateinit var bar: Lazy


    }
    get()ਸ ഐ୹ೞݶ, ୭ୡ ೠߣ݅ ࢤࢿೠ׮. Scope৬ ਬࢎೞ׮.
    fun doSomething() {


    bar.get().doSomething()


    }

    View Slide

  60. public final class DoubleCheck implements Provider, Lazy {


    ...


    public static , T> Provider provider(P delegate) {


    if (delegate instanceof DoubleCheck) {


    return delegate;


    }


    return new DoubleCheck(delegate);


    }


    public static , T> Lazy lazy(P provider) {


    if (provider instanceof Lazy) {


    final Lazy lazy = (Lazy) provider;


    return lazy;


    }


    return new DoubleCheck(provider);


    }


    }
    DoubleCheck.provider() ≈ DoubleCheck.lazy()

    View Slide

  61. Lazy: Advanced
    private static final class ActivityCImpl extends ActivityC {


    private Provider barProvider = new SwitchingProvider(..., 0);


    public void injectExampleActivity(ExampleActivity instance) {


    ExampleActivity_MembersInjector.injectBar(instance, DoubleCheck.lazy(this.barProvider));


    ExampleActivity_MembersInjector.injectExampleUseCase(instance,


    new ExampleUseCase(DoubleCheck.lazy(this.barProvider)));


    }


    }
    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject


    lateinit var bar: Lazy


    @Inject


    lateinit var useCase: ExampleUseCase


    }
    ೞ૑݅ @Inject ݃׮ ࢲ۽ ׮ܲ ё୓ܳ ࢤࢿೠ׮. ૊, Barо ৈ۞ ߣ ࢤࢿؼ ࣻ ੓׮.
    class ExampleUseCase @Inject constructor(


    private val bar: Lazy


    ) { ... }

    View Slide

  62. Scope + Provider
    private static final class ActivityCImpl extends ActivityC {


    private Provider barProvider = DoubleCheck.provider(new SwitchingProvider(..., 0));


    public void injectExampleActivity(ExampleActivity instance) {


    ExampleActivity_MembersInjector.injectBar(instance, this.barProvider);


    }


    }
    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject


    lateinit var bar: Provider


    }
    ё୓ܳ ೠߣ݅ ૑ো ࢤࢿೞ۰ݶ, Lazyࠁ׮ח Scope + Providerܳ ࢎਊೞ੗.
    @ActivityScoped


    class Bar @Inject constructor()

    View Slide

  63. Scope
    private static final class ActivityCImpl extends ActivityC {


    private Provider barProvider = DoubleCheck.provider(new SwitchingProvider(..., 0));


    public void injectExampleActivity(ExampleActivity instance) {


    ExampleActivity_MembersInjector.injectBar(instance, this.barProvider.get());


    }


    }
    @AndroidEntryPoint


    class ExampleActivity : ComponentActivity() {


    @Inject


    lateinit var bar: Bar


    }
    (ܻ݃ੋ٘) Scope݅ ૑੿ೠ ҃਋ীח ࢤࢿೞৈ ઱ੑೠ׮.
    @ActivityScoped


    class Bar @Inject constructor()

    View Slide

  64. EntryPoint
    Hiltо ૑ਗೞ૑ ঋח ௿ېझী ੄ઓࢿਸ ઁҕೞח ߑߨ (ex. ContentProvider)
    class Bar @Inject constructor()


    @EntryPoint


    @InstallIn(SingletonComponent::class)


    interface ExampleEntryPoint {


    fun bar(): Bar


    }


    val entryPoint = EntryPointAccessors.fromApplication(


    context = context,


    entryPoint = ExampleEntryPoint::class.java,


    )


    val bar: Bar = entryPoint.bar()

    View Slide

  65. @EntryPoint


    @InstallIn(SingletonComponent::class)


    interface ExampleEntryPoint {


    fun bar(): Bar


    }


    // --------------------------------------------------------------------------------


    // Generated by Hilt


    public final class ExampleApplication_HiltComponents {


    @Component(modules = { ... })


    @Singleton


    public abstract static class SingletonC


    implements SingletonComponent, GeneratedComponent, ExampleEntryPoint {


    }


    }


    // --------------------------------------------------------------------------------


    // Generated by Dagger


    public final class DaggerExampleApplication_HiltComponents_SingletonC {


    private static final class SingletonCImpl extends SingletonC {


    public Bar bar() { return new Bar(); }


    }


    ...


    } (1) EntryPointо ੄ઓࢿ Ӓې೐ী ୶оػ׮.

    View Slide

  66. val entryPoint = EntryPointAccessors.fromApplication(


    context = context,


    entryPoint = ExampleEntryPoint::class.java,


    )


    // --------------------------------------------------------------------------------


    object EntryPointAccessors {


    fun fromApplication(context: Context, entryPoint: Class): T =


    EntryPoints.get(Contexts.getApplication(context.applicationContext), entryPoint)


    }


    // --------------------------------------------------------------------------------


    public final class EntryPoints {


    public static T get(Object component, Class entryPoint) {


    if (component instanceof GeneratedComponent) {


    return entryPoint.cast(component);


    } else if (component instanceof GeneratedComponentManager) {


    return get(((GeneratedComponentManager>) component).generatedComponent(), entryPoint);


    } else {


    throw new IllegalStateException("...");


    }


    }


    } (2) Applicationਸ ఐ࢝ೞৈ, EntryPointо ҳഅػ Componentܳ оઉৡ׮.

    View Slide

  67. val entryPoint = EntryPointAccessors.fromApplication(


    context = context,


    entryPoint = ExampleEntryPoint::class.java,


    )


    // --------------------------------------------------------------------------------


    object EntryPointAccessors {


    fun fromApplication(context: Context, entryPoint: Class): T =


    EntryPoints.get(Contexts.getApplication(context.applicationContext), entryPoint)


    }


    // --------------------------------------------------------------------------------


    public final class EntryPoints {


    public static T get(Object component, Class entryPoint) {


    if (component instanceof GeneratedComponent) {


    return entryPoint.cast(component);


    } else if (component instanceof GeneratedComponentManager) {


    return get(((GeneratedComponentManager>) component).generatedComponent(), entryPoint);


    } else {


    throw new IllegalStateException("...");


    }


    }


    } GeneratedComponentManager???

    View Slide

  68. // Generated by Hilt


    public final class ExampleApplication_HiltComponents {


    @Component(modules = { ... })


    @Singleton


    public abstract static class SingletonC


    implements SingletonComponent, GeneratedComponent, ExampleEntryPoint {


    }


    }


    // --------------------------------------------------------------------------------


    public abstract class Hilt_ExampleApplication extends Application


    implements GeneratedComponentManager {


    private final ApplicationComponentManager componentManager = ...;


    public final Object generatedComponent() {


    return this.componentManager.generatedComponent();


    }


    }
    = Hilt_ExampleApplication

    View Slide

  69. DaggerExampleApplication_HiltComponents_SingletonC
    SingletonCImpl
    EntryPoint flow
    ExampleEntryPoint
    EntryPoints Bar
    GeneratedComponent
    GeneratedComponentManager
    ੿ܻೞݶ, ੉۠ ൒ܴਵ۽ ੄ઓࢿਸ оઉৡ׮.

    View Slide

  70. EntryPointܳ ഝਊೞৈ, ੄ઓࢿਸ ઱ੑೞҊ ੓׮.

    ❏ ViewModel

    ❏ WorkManager

    ❏ Navigation

    Jetpack ௿ېझী ઱ੑغח җ੿਷,

    “I/O Extended 2023 Seoul” ীࢲ੄ ߊ಴੗ܐܳ ଵҊ೧઱ࣁਃ.
    Jetpack Libraries
    Link: h
    tt
    ps://speakerdeck.com/fornewid/dagger-hiltro-yijonseong-juibhagi?slide=38

    View Slide

  71. ݣ౭ݽٕীࢲ੄ ੄ઓࢿ ઱ੑ.
    ⚠ ਊয ੿ܻ: ݽٕ = Gradle Module / @Module = Dagger Module

    View Slide

  72. App Modularization
    Link: h
    tt
    ps://developer.android.com/topic/modularization
    :app:android
    :feature:home
    :data:books
    :feature:reviews :feature:player
    :app:auto
    :core:network
    :data:reviews
    ਃ્ জ਷ ӝמ੉ ݆ই૑ݶࢲ, ੼੼ ؊ ݽٕਸ ࣁ࠙ചೞҊ ੓׮.

    View Slide

  73. Gradle Build Setup
    plugins {


    id 'com.google.dagger.hilt.android'


    id 'kotlin-kapt'


    }


    dependencies {


    implementation 'com.google.dagger:hilt-android:2.48'


    kapt 'com.google.dagger:hilt-compiler:2.48'


    }
    ݽٕਸ ୶оೡ ٸ݃׮ ۄ੉࠳۞ܻ ࢸ஖ܳ ߈ࠂೠ׮.

    ੉ח Convention Pluginsਵ۽ ѐࢶೡ ࣻ ੓׮.

    “Gradle Kotlin ஶ߮࣌ ೒۞Ӓੋਵ۽ ബਯ੸ਵ۽ ݣ౭ ݽٕ ҙܻೞӝ” ߊ಴ܳ ଵҊ೧ ࠅ Ѫ.
    plugins {


    id 'example.android.hilt'


    }

    View Slide

  74. App Modularization: @Module
    Link: h
    tt
    ps://developer.android.com/topic/modularization
    :app:android
    :feature:home
    :data:books
    :feature:reviews :feature:player
    :app:auto
    :core:network
    :data:reviews
    @Module
    @Module
    @Module
    п ݽٕ݃׮ @Moduleਸ ੿੄ೡ ࣻ ੓׮.

    View Slide

  75. App Modularization: @Module
    :app:android
    :feature:home
    :data:books
    :core:network
    @Module


    @InstallIn(SingletonComponent::class)


    object FeatureHomeModule { ... }
    @Module


    @InstallIn(SingletonComponent::class)


    object DataBooksModule { ... }
    @Module


    @InstallIn(SingletonComponent::class)


    object CoreNetworkModule { ... }
    @HiltAndroidApp


    class MyApp : Application()
    ௏٘۽ח ੉۠ ഋకо ؼ ࣻ ੓׮.

    View Slide

  76. hilt_metadata
    Without Classpath Aggregation
    :app:android
    :feature:home
    :data:books
    :core:network
    implementation
    implementation
    api
    @Metadata
    @Metadata
    @InstallIn
    @InstallIn
    @InstallIn
    @Generated("dagger.hilt")


    interface MyApp_HiltComponents {


    @Component(modules = [


    FeatureHomeModule::class,


    DataBooksModule::class,


    ...


    ])


    interface SingletonC


    }
    Link: h
    tt
    ps://medium.com/androiddevelopers/mad-skills-series-hilt-under-the-hood-9d89ee227059
    ೞ૑݅ জ ݽٕীࢲ ੽Ӕೡ ࣻ হח @Module਷ জ ੄ઓࢿ Ӓې೐ী ನೣؼ ࣻ হ׮.
    CoreNetworkModule::class,

    View Slide

  77. hilt_metadata
    With Classpath Aggregation
    :app:android
    :feature:home
    :data:books
    :core:network
    implementation
    implementation
    api
    @Metadata
    @Metadata
    @Metadata
    @InstallIn
    @InstallIn
    @InstallIn
    @Generated("dagger.hilt")


    interface MyApp_HiltComponents {


    @Component(modules = [


    FeatureHomeModule::class,


    DataBooksModule::class,


    ...


    ])


    interface SingletonC


    }
    Link: h
    tt
    ps://medium.com/androiddevelopers/mad-skills-series-hilt-under-the-hood-9d89ee227059
    Classpath Aggregationਸ ੉ਊೞৈ, ੉ ޙઁܳ ೧ѾೞҊ ੓׮.
    CoreNetworkModule::class,

    View Slide

  78. App Architecture
    UI Layer
    Domain Layer
    Data Layer
    Link: h
    tt
    ps://developer.android.com/topic/architecture
    উ٘۽੉٘ ҕध ޙࢲীࢲ ӂ੢ೞח জ ইఃఫ୊

    View Slide

  79. App Architecture
    :ui
    :domain
    :data
    Link: h
    tt
    ps://developer.android.com/topic/architecture
    implementation
    implementation
    ੉۠ ݽٕ ҳઑۄҊ о੿೧ࠁ੗.

    View Slide

  80. App Architecture
    :data
    class ExampleUseCase @Inject constructor(


    private val repository: ExampleRepository


    ) { ... }
    :ui
    :domain
    class ExampleRepository @Inject constructor(


    ) { ... }
    Hiltܳ ੉ਊೞৈ, ׮ܲ ݽٕ੄ ੄ઓࢿਸ ઱ੑೡ ࣻ ੓׮.

    View Slide

  81. App Architecture: interface, class ܻ࠙
    :domain
    :data
    class ExampleUseCase @Inject constructor(


    private val repository: ExampleRepository


    ) { ... }
    class ExampleRepository @Inject constructor(


    ) { ... }
    ҳഅ୓ী ૒੽ ੄ઓࢿਸ ыח Ѫ ࠁ׮ח,

    View Slide

  82. App Architecture: interface, class ܻ࠙
    :domain
    :data
    interface ExampleRepository


    class ExampleRepositoryImpl @Inject constructor(


    ) : ExampleRepository { ... }


    @Module


    @InstallIn(SingletonComponent::class)


    interface DataModule {


    @Binds fun bindRepository(


    impl: ExampleRepositoryImpl


    ) : ExampleRepository


    }
    class ExampleUseCase @Inject constructor(


    private val repository: ExampleRepository


    ) { ... }
    inte
    rf
    ace৬ classܳ ܻ࠙ೞৈ, ҳഅ୓ܳ ૒੽ ଵઑೞ૑ ঋب۾ ѐࢶೡ ࣻ ੓׮.

    View Slide

  83. App Architecture: internal
    :domain
    :data
    Link: h
    tt
    ps://kotlinlang.org/docs/visibility-modi
    fi
    ers.html#modules
    interface ExampleRepository


    internal class ExampleRepositoryImpl @Inject constructor(


    ) : ExampleRepository { ... }


    @Module


    @InstallIn(SingletonComponent::class)


    internal interface DataModule {


    @Binds fun bindRepository(


    impl: ExampleRepositoryImpl


    ) : ExampleRepository


    }
    class ExampleUseCase @Inject constructor(


    private val repository: ExampleRepository


    ) { ... }
    ؊ աইо ݽٕ ৻ࠗীࢲח ੽Ӕೡ ࣻ হب۾, internal ఃਕ٘ܳ ੉ਊೡ ࣻ ੓׮.

    View Slide

  84. internal @Module
    @OriginatingElement(topLevelClass = DataModule.class)


    @InstallIn(SingletonComponent.class)


    @Module(includes = DataModule.class)


    public final class HiltWrapper_DataModule {}
    @Module


    @InstallIn(SingletonComponent::class)


    internal interface DataModule {


    @Binds


    fun bindRepository(impl: ExampleRepositoryImpl) : ExampleRepository


    }
    internal @Module਷ ݽٕ ৻ࠗীࢲ ੽Ӕೡ ࣻ হਵ޲۽, HiltWrapperܳ ࢤࢿೞৈ

    View Slide

  85. internal @Module ؀न Componentী ୶о೧ળ׮. Ӓ۞ա…
    public final class ExampleApplication_HiltComponents {


    @Component(


    modules = {


    ApplicationContextModule.class,


    ActivityRetainedCBuilderModule.class,


    HiltWrapper_DataModule.class,


    }


    )


    @Singleton


    public abstract static class SingletonC implements


    HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,


    SingletonComponent,


    GeneratedComponent {


    }


    }

    View Slide

  86. App Architecture: internal ޙઁ੼
    ௿ېझ݃׮ internal ఃਕ٘ܳ ୶о೧ঠ ೠ׮. (߈ࠂ ੘স)
    =

    “׮ܲ ߑߨਸ Ҋ޹೧ࠁ੗…”
    =

    ѐߊ੗о ֬஖ӝ औ׮. (पࣻ ਬߊ)

    View Slide

  87. App Architecture: Clean Architecture ֤ۆ?
    UI Layer
    Domain Layer
    Data Layer
    Link: h
    tt
    ps://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
    UI Layer
    Domain Layer
    Data Layer
    interface ExampleRepository
    interface ExampleRepository
    vs
    inte
    rf
    aceܳ بݫੋ ݽٕ۽ ੉زೠ׮ݶ???

    View Slide

  88. App Architecture: Clean Architecture ֤ۆ?
    :domain
    :data
    interface ExampleRepository


    internal class ExampleRepositoryImpl @Inject constructor(


    ) : ExampleRepository { ... }


    @Module


    @InstallIn(SingletonComponent::class)


    internal interface DataModule {


    @Binds fun bindRepository(


    impl: ExampleRepositoryImpl


    ) : ExampleRepository


    }
    class ExampleUseCase @Inject constructor(


    private val repository: ExampleRepository


    ) { ... }

    View Slide

  89. App Architecture: Clean Architecture ֤ۆ?
    :domain
    :data
    class ExampleUseCase @Inject constructor(


    private val repository: ExampleRepository


    ) { ... }


    interface ExampleRepository
    internal class ExampleRepositoryImpl @Inject constructor(


    ) : ExampleRepository { ... }


    @Module


    @InstallIn(SingletonComponent::class)


    internal interface DataModule {


    @Binds fun bindRepository(


    impl: ExampleRepositoryImpl


    ) : ExampleRepository


    }
    Ӓۡ٠೧ ࠁੋ׮. بݫੋ ݽٕ੉ ೞաۄݶ…

    View Slide

  90. App Architecture: Clean Architecture ֤ۆ?
    :domain-qux
    :domain-baz
    :domain-bar
    :domain-foo
    interface Baz


    class BazImpl(bar: Bar) : Baz
    interface Bar


    class BarImpl(foo: Foo) : Bar
    interface Foo


    class FooImpl() : Foo
    interface Qux


    class QuxImpl(baz: Baz) : Qux
    بݫੋ ݽٕ੉ ৈۤ੉ݶ, inte
    rf
    aceܳ য٣ী ىঠ ೡө???

    View Slide

  91. App Architecture: Clean Architecture ֤ۆ?
    :domain-qux
    :domain-baz
    :domain-bar
    :domain-foo
    class BazImpl(bar: Bar) : Baz


    interface Bar
    class BarImpl(foo: Foo) : Bar


    interface Foo
    class FooImpl() : Foo
    interface Qux


    class QuxImpl(baz: Baz) : Qux


    interface Baz
    ࢎਊೞח ݽٕ۽ ৤ѹঠ ೞա???

    View Slide

  92. App Architecture: Clean Architecture ֤ۆ?
    :domain-qux
    :domain-bar
    :domain-foo
    interface Bar


    class BarImpl(foo: Foo) : Bar
    interface Foo


    class FooImpl() : Foo
    interface Qux


    class QuxImpl(bar: Bar) : Qux
    Ӓۢ ৈ۞ ݽٕীࢲ ೞա੄ inte
    rf
    aceܳ ࢎਊೞҊ ੓׮ݶ???
    interface Baz


    class BazImpl(bar: Bar) : Baz
    :domain-baz

    View Slide

  93. App Architecture: Clean Architecture ֤ۆ?
    :domain-qux
    :domain-bar
    :domain-foo
    class BarImpl(foo: Foo) : Bar


    interface Foo
    class FooImpl() : Foo
    interface Qux


    class QuxImpl(bar: Bar) : Qux


    interface Bar
    inte
    rf
    aceܳ ৤ӡ ਤ஖о গݒೞ׮…
    :domain-baz
    interface Baz


    class BazImpl(bar: Bar) : Baz


    interface Bar

    View Slide

  94. App Architecture: ݽٕ ܻ࠙
    :domain-qux
    :domain-bar-api
    inte
    rf
    ace৬ classܳ пп ׮ܲ ݽٕ۽ ܻ࠙ೞݶ ೧Ѿػ׮!
    :domain-baz
    :domain-bar-impl
    interface Bar
    class BarImpl(foo: Foo) : Bar
    interface Qux


    class QuxImpl(bar: Bar) : Qux
    interface Baz


    class BazImpl(bar: Bar) : Baz

    View Slide

  95. App Architecture: ݽٕ ܻ࠙
    :domain-qux
    :domain-bar-api
    ҳഅ୓ח @Moduleਸ ా೧ ઱ੑೠ׮.
    :domain-baz
    :domain-bar-impl
    interface Bar
    class BarImpl(foo: Foo) : Bar ->
    interface Qux


    class QuxImpl(bar: Bar) : Qux
    @Module
    interface Baz


    class BazImpl(bar: Bar) : Baz

    View Slide

  96. App Architecture: ݽٕ ܻ࠙
    :domain-qux-impl
    :domain-baz-impl
    :domain-bar-impl
    :domain-foo-impl
    class BazImpl(bar: Bar) : Baz
    class BarImpl(foo: Foo) : Bar
    class FooImpl() : Foo
    class QuxImpl(baz: Baz) : Qux
    ݽٕ ױਤী ੄ઓࢿ ৉੹ ਗ஗(DIP)ਸ ੸ਊೡ ࣻ ੓׮.
    :domain-qux-api
    :domain-baz-api
    :domain-bar-api
    :domain-foo-api
    interface Baz
    interface Bar
    interface Foo
    interface Qux
    Link: h
    tt
    ps://en.wikipedia.org/wiki/Dependency_inversion_principle

    View Slide

  97. App Modularization: Final!
    :app:android
    :feature:home-api :data:books-api
    :data:books-impl
    :app:android
    :feature:home
    :data:books
    :feature:home-impl
    Before After
    ୭ઙ੸ਵ۽ জ ݽٕ݅ ࣁࠗ ݽٕী ੽Ӕೡ ࣻ ੓ѱ ѐࢶೡ ࣻ ੓׮.

    View Slide

  98. App Modularization: Final! (+ runtimeOnly)
    :app:android
    :feature:home-api :data:books-api
    :data:books-impl
    runtimeOnly
    :app:android
    :feature:home
    :data:books
    :feature:home-impl
    runtimeOnly
    Before After
    Link: h
    tt
    ps://developer.android.com/build/dependencies#runtimeOnly
    জ ݽٕب ੽Ӕೞ૑ ޅೞѱ, ੄ઓࢿ Ӓې೐ী݅ ನೣغب۾ ೡ ࣻب ੓׮.

    View Slide

  99. Summary
    ❏ Dagger Hilt ղࠗ௏٘ ࠙ࢳ

    • ੄ઓࢿ Ӓې೐о ࢤࢿغҊ, ੄ઓࢿਸ ઱ੑೞח ੹߈੸ੋ җ੿ਸ ঌইࠌ׮.

    • @Provides ࠁ׮ח @Inject, @Bindsਸ ࢎਊೞ੗.

    • Scopeܳ ࢶ঱ೞח ਤ஖ܳ ઱੄ೞ੗.

    • Lazyࠁ׮ח Scope + Providerਸ ࢎਊೞ੗.

    ❏ ݣ౭ݽٕীࢲ੄ ੄ઓࢿ ઱ੑ

    • Convention Pluginsਸ ࢎਊೞ੗.

    • internal ࠁ׮ח, ݽٕਸ ܻ࠙ೞৈ ੽Ӕਸ ઁೠೞ੗. (api, impl)
    Sample: h
    tt
    ps://github.com/fornewid/dagger-hilt-example/

    View Slide

  100. хࢎ೤פ׮!
    Slide Link: h
    tt
    ps://speakerdeck.com/fornewid

    View Slide