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

Video: https://youtu.be/iE_2llWUI6A

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/