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

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

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for Sungyong An Sungyong An
September 12, 2023

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

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

Video: https://youtu.be/iE_2llWUI6A

Avatar for Sungyong An

Sungyong An

September 12, 2023
Tweet

More Decks by Sungyong An

Other Decks in Programming

Transcript

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

    ӝߨ੉׮. ੄ઓࢿ ઱ੑ੄ ੄بח ё୓੄ ࢤࢿҗ ࢎਊ੄ ҙबਸ ܻ࠙ೞח Ѫ੉׮. DI ਗ஗ਸ ٮܰݶ ഴܯೠ জ ইఃఫ୊ܳ ਤೠ ష؀ܳ ݃۲ೡ ࣻ ੓׮. • ௏٘ ੤ࢎਊ оמ • ܻಂష݂ ಞ੄ࢿ • పझ౟ ಞ੄ࢿ Link: h tt ps://en.wikipedia.org/wiki/Dependency_injection
  2. // 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
  3. // 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
  4. // 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
  5. 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
  6. @Module @InstallIn(SingletonComponent::class) class EngineModule { @Provides // construct fun providesEngine():

    Engine = Engine() } Link: h tt ps://dagger.dev/hilt/quick-sta r @Provides ١ਸ ੉ਊೞৈ, ੄ઓࢿਸ ઁҕೡ ࣻ ੓׮. Engine
  7. @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
  8. @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
  9. @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ਸ ࢓ಝࠁݶ, ੄ઓࢿ ઱ੑҗ ҙ۲ػ ௏٘о হ׮???
  10. // 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!
  11. “Dagger Hiltо ࢤࢿೞח ௏٘ܳ ࠙ࢳೞৈ, 
 Hiltо উ٘۽੉٘ জী ੄ઓࢿਸ

    ઱ੑೞח җ੿ਸ ੉೧೧ ࠁ੗.” Goal + “ݣ౭ ݽٕীࢲ੄ ࢎਊ ߑߨਸ Ҋ޹೧ ࠁ੗.” ⚠ ठۄ੉٘੄ ௏٘ח Dagger Hilt 2.48 ߡ੹ਸ ӝળਵ۽ ੘ࢿغ঻णפ׮.
  12. 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 ౵ੌٜ੉ ࢤࢿػ׮.
  13. 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 ӏ஗੉ ࠁ੉աਃ?
  14. 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੉ ੓׮???
  15. @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਷ জ੄ ੄ઓࢿ Ӓې೐ܳ ࢤࢿೞח ӝળ੉ ػ׮.
  16. @HiltAndroidApp class ExampleApplication : Application() { @Inject lateinit var bar:

    Bar } Bar Overview ExampleApplication DaggerExampleApplication_HiltComponents_SingletonC ExampleActivity FooModule (1) ӝࠄ ࢤࢿغח ੄ઓࢿ Ӓې೐ܳ ࢓ಝࠁ੗.
  17. 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.
  18. public final class ExampleApplication_HiltComponents { @Component( modules = { ApplicationContextModule.class,

    ActivityRetainedCBuilderModule.class, } ) @Singleton public abstract static class SingletonC implements HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint, SingletonComponent, GeneratedComponent { } }
  19. 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݃׮ ੉۠ ௿ېझо ࢤࢿػ׮.
  20. 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ী ؀਽ೞח ௿ېझ.
  21. 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 ࢚ਤ ஹನք౟੄ ੄ઓࢿਸ ೞਤী ઱ੑೡ ࣻ ੓Ҋ, ৉ਵ۽ח ೡ ࣻ হ׮. যڌѱ???
  22. 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 ) { ... } } }
  23. 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.
  24. @Module @InstallIn(SingletonComponent::class) object FooModule { @Provides fun provideBar(): Bar =

    Bar() } Bar Overview ExampleApplication DaggerExampleApplication_HiltComponents_SingletonC ExampleActivity (2) ૒੽ ੿੄ೠ ੄ઓࢿ੉ Ӓې೐ী যڌѱ ୶оغח૑ ࢓ಝࠁ੗. FooModule
  25. @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੉ ୶оػ׮.
  26. @Module @InstallIn(SingletonComponent::class) object FooModule { @Provides fun provideBar(): Bar =

    Bar() } // -------------------------------------------------------------------------------- public final class FooModule_ProvideBarFactory implements Factory<Bar> { public static Bar provideBar() { return Preconditions.checkNotNullFromProvides(FooModule.INSTANCE.provideBar()); } } @Provides݃׮ ੄ઓࢿਸ ઁҕೞח Factory ௿ېझо ࢤࢿػ׮.
  27. @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
  28. 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) { } }
  29. ExampleApplication_MembersInjector.java @HiltAndroidApp class ExampleApplication : Application() { @Inject lateinit var

    bar: Bar } // -------------------------------------------------------------------------------- public final class ExampleApplication_MembersInjector implements MembersInjector<ExampleApplication> { 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ী ੸੺൤ ୶оػ׮.
  30. Hilt_ExampleApplication.java @HiltAndroidApp class ExampleApplication : Application() { @Inject lateinit var

    bar: Bar } = @HiltAndroidApp class ExampleApplication : Hilt_ExampleApplication() { @Inject lateinit var bar: Bar } ߄੉౟௏٘ܳ ߸ജೞৈ, ࠗݽ ௿ېझܳ ߸҃ೠ׮.
  31. 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ী ੽Ӕೞৈ, ੄ઓࢿ ઱ੑਸ ਃ୒ೠ׮.
  32. @Module @InstallIn(SingletonComponent::class) object FooModule { @Provides fun provideBar(): Bar =

    Bar() } @Provides Bar ExampleApplication DaggerExampleApplication_HiltComponents_SingletonC ExampleActivity FooModule_ProvideBarFactory
  33. @Module @InstallIn(SingletonComponent::class) object FooModule { @Provides fun provideBar(): Bar =

    Bar() } // -------------------------------------------------------------------------------- public final class FooModule_ProvideBarFactory implements Factory<Bar> { 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 ௿ېझܳ ా೧ ੄ઓࢿਸ ઁҕೠ׮.
  34. class Bar @Inject constructor() // -------------------------------------------------------------------------------- private static final class

    SingletonCImpl extends SingletonC { public void injectExampleApplication(ExampleApplication instance) { ExampleApplication_MembersInjector.injectBar(instance, new Bar()); } } @Injectח ߹ب੄ ௏٘হ੉, ੄ઓࢿਸ ߄۽ ઁҕೠ׮.
  35. 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
  36. 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ܳ ೣԋ ࢎਊ೧ب زੌೞ׮.
  37. @Singleton class Bar @Inject constructor() // -------------------------------------------------------------------------------- private static final

    class SingletonCImpl extends SingletonC { private Provider<Bar> 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<T> implements Provider<T> { public T get() { switch (this.id) { case 0: return new Bar(); default: throw new AssertionError(this.id); } } } } Scopeܳ ࢶ঱ೞݶ, ೧׼ Componentী Providerܳ ࢤࢿೠ׮.
  38. public final class DoubleCheck<T> implements Provider<T>, Lazy<T> { 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 <P extends Provider<T>, T> Provider<T> provider(P delegate) { return new DoubleCheck<T>(delegate); } } DoubleCheckח ё୓ܳ ೞա݅ ࢤࢿೠ׮.
  39. Scope: Advanced private static final class SingletonCImpl extends SingletonC {

    private Provider<BarImpl> barImplProvider = new SwitchingProvider(this, 0); private Provider<Bar> 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 }
  40. Scope: Advanced private static final class SingletonCImpl extends SingletonC {

    private Provider<BarImpl> barImplProvider = new SwitchingProvider(this, 0); private Provider<Bar> bindBarProvider = DoubleCheck.provider(this.barImplProvider); private Provider<Bar2> 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੉ ৈ۞ ߣ ࢤࢿؼ ࣻب ੓׮.
  41. Scope: Advanced private static final class SingletonCImpl extends SingletonC {

    private Provider<BarImpl> 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ܳ ࢶ঱ೞח ਤ஖ܳ ઱੄ೞ੗!
  42. @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 }
  43. @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 ݃׮ ࢲ۽ ׮ܲ ё୓ܳ ࢤࢿೠ׮.
  44. Provider private static final class ActivityCImpl extends ActivityC { private

    Provider<Bar> barProvider = new SwitchingProvider(..., 0); public void injectExampleActivity(ExampleActivity instance) { ExampleActivity_MembersInjector.injectBar(instance, this.barProvider); } } @AndroidEntryPoint class ExampleActivity : ComponentActivity() { @Inject lateinit var bar: Provider<Bar> } get()ਸ ഐ୹ೡ ٸ݃׮, ࢤࢿೠ׮. fun doSomething() { bar.get().doSomething() }
  45. Lazy private static final class ActivityCImpl extends ActivityC { private

    Provider<Bar> 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<Bar> } get()ਸ ഐ୹ೞݶ, ୭ୡ ೠߣ݅ ࢤࢿೠ׮. Scope৬ ਬࢎೞ׮. fun doSomething() { bar.get().doSomething() }
  46. public final class DoubleCheck<T> implements Provider<T>, Lazy<T> { ... public

    static <P extends Provider<T>, T> Provider<T> provider(P delegate) { if (delegate instanceof DoubleCheck) { return delegate; } return new DoubleCheck<T>(delegate); } public static <P extends Provider<T>, T> Lazy<T> lazy(P provider) { if (provider instanceof Lazy) { final Lazy<T> lazy = (Lazy<T>) provider; return lazy; } return new DoubleCheck<T>(provider); } } DoubleCheck.provider() ≈ DoubleCheck.lazy()
  47. Lazy: Advanced private static final class ActivityCImpl extends ActivityC {

    private Provider<Bar> 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<Bar> @Inject lateinit var useCase: ExampleUseCase } ೞ૑݅ @Inject ݃׮ ࢲ۽ ׮ܲ ё୓ܳ ࢤࢿೠ׮. ૊, Barо ৈ۞ ߣ ࢤࢿؼ ࣻ ੓׮. class ExampleUseCase @Inject constructor( private val bar: Lazy<Bar> ) { ... }
  48. Scope + Provider private static final class ActivityCImpl extends ActivityC

    { private Provider<Bar> 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<Bar> } ё୓ܳ ೠߣ݅ ૑ো ࢤࢿೞ۰ݶ, Lazyࠁ׮ח Scope + Providerܳ ࢎਊೞ੗. @ActivityScoped class Bar @Inject constructor()
  49. Scope private static final class ActivityCImpl extends ActivityC { private

    Provider<Bar> 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()
  50. 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()
  51. @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о ੄ઓࢿ Ӓې೐ী ୶оػ׮.
  52. val entryPoint = EntryPointAccessors.fromApplication( context = context, entryPoint = ExampleEntryPoint::class.java,

    ) // -------------------------------------------------------------------------------- object EntryPointAccessors { fun <T> fromApplication(context: Context, entryPoint: Class<T>): T = EntryPoints.get(Contexts.getApplication(context.applicationContext), entryPoint) } // -------------------------------------------------------------------------------- public final class EntryPoints { public static <T> T get(Object component, Class<T> 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ܳ оઉৡ׮.
  53. val entryPoint = EntryPointAccessors.fromApplication( context = context, entryPoint = ExampleEntryPoint::class.java,

    ) // -------------------------------------------------------------------------------- object EntryPointAccessors { fun <T> fromApplication(context: Context, entryPoint: Class<T>): T = EntryPoints.get(Contexts.getApplication(context.applicationContext), entryPoint) } // -------------------------------------------------------------------------------- public final class EntryPoints { public static <T> T get(Object component, Class<T> 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???
  54. // 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<Object> { private final ApplicationComponentManager componentManager = ...; public final Object generatedComponent() { return this.componentManager.generatedComponent(); } } = Hilt_ExampleApplication
  55. 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
  56. 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 ਃ્ জ਷ ӝמ੉ ݆ই૑ݶࢲ, ੼੼ ؊ ݽٕਸ ࣁ࠙ചೞҊ ੓׮.
  57. 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' }
  58. 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ਸ ੿੄ೡ ࣻ ੓׮.
  59. 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() ௏٘۽ח ੉۠ ഋకо ؼ ࣻ ੓׮.
  60. 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,
  61. 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,
  62. App Architecture UI Layer Domain Layer Data Layer Link: h

    tt ps://developer.android.com/topic/architecture উ٘۽੉٘ ҕध ޙࢲীࢲ ӂ੢ೞח জ ইఃఫ୊
  63. App Architecture :data class ExampleUseCase @Inject constructor( private val repository:

    ExampleRepository ) { ... } :ui :domain class ExampleRepository @Inject constructor( ) { ... } Hiltܳ ੉ਊೞৈ, ׮ܲ ݽٕ੄ ੄ઓࢿਸ ઱ੑೡ ࣻ ੓׮.
  64. App Architecture: interface, class ܻ࠙ :domain :data class ExampleUseCase @Inject

    constructor( private val repository: ExampleRepository ) { ... } class ExampleRepository @Inject constructor( ) { ... } ҳഅ୓ী ૒੽ ੄ઓࢿਸ ыח Ѫ ࠁ׮ח,
  65. 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ܳ ܻ࠙ೞৈ, ҳഅ୓ܳ ૒੽ ଵઑೞ૑ ঋب۾ ѐࢶೡ ࣻ ੓׮.
  66. 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 ఃਕ٘ܳ ੉ਊೡ ࣻ ੓׮.
  67. 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ܳ ࢤࢿೞৈ
  68. 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 { } }
  69. App Architecture: internal ޙઁ੼ ௿ېझ݃׮ internal ఃਕ٘ܳ ୶о೧ঠ ೠ׮. (߈ࠂ

    ੘স) = “׮ܲ ߑߨਸ Ҋ޹೧ࠁ੗…” = ѐߊ੗о ֬஖ӝ औ׮. (पࣻ ਬߊ)
  70. 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ܳ بݫੋ ݽٕ۽ ੉زೠ׮ݶ???
  71. 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 ) { ... }
  72. 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 } Ӓۡ٠೧ ࠁੋ׮. بݫੋ ݽٕ੉ ೞաۄݶ…
  73. 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ܳ য٣ী ىঠ ೡө???
  74. 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 ࢎਊೞח ݽٕ۽ ৤ѹঠ ೞա???
  75. 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
  76. 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
  77. 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
  78. 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
  79. 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
  80. 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 ୭ઙ੸ਵ۽ জ ݽٕ݅ ࣁࠗ ݽٕী ੽Ӕೡ ࣻ ੓ѱ ѐࢶೡ ࣻ ੓׮.
  81. 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 জ ݽٕب ੽Ӕೞ૑ ޅೞѱ, ੄ઓࢿ Ӓې೐ী݅ ನೣغب۾ ೡ ࣻب ੓׮.
  82. 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/