Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Sungyong An NAVER WEBTOON Android GDE @fornewid Link: h tt ps://github.com/fornewid

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Dependency Injection ੄ઓࢿ ઱ੑ(DI)਷ ೞա੄ ё୓о ׮ܲ ё୓੄ ੄ઓࢿਸ ઁҕೞח ӝߨ੉׮. ੄ઓࢿ ઱ੑ੄ ੄بח ё୓੄ ࢤࢿҗ ࢎਊ੄ ҙबਸ ܻ࠙ೞח Ѫ੉׮. DI ਗ஗ਸ ٮܰݶ ഴܯೠ জ ইఃఫ୊ܳ ਤೠ ష؀ܳ ݃۲ೡ ࣻ ੓׮. • ௏٘ ੤ࢎਊ оמ • ܻಂష݂ ಞ੄ࢿ • పझ౟ ಞ੄ࢿ Link: h tt ps://en.wikipedia.org/wiki/Dependency_injection

Slide 5

Slide 5 text

// 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

Slide 6

Slide 6 text

// 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

Slide 7

Slide 7 text

// 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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

@Module @InstallIn(SingletonComponent::class) class EngineModule { @Provides // construct fun providesEngine(): Engine = Engine() } Link: h tt ps://dagger.dev/hilt/quick-sta r @Provides ١ਸ ੉ਊೞৈ, ੄ઓࢿਸ ઁҕೡ ࣻ ੓׮. Engine

Slide 10

Slide 10 text

@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

Slide 11

Slide 11 text

@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

Slide 12

Slide 12 text

@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ਸ ࢓ಝࠁݶ, ੄ઓࢿ ઱ੑҗ ҙ۲ػ ௏٘о হ׮???

Slide 13

Slide 13 text

// 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!

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Dagger Hilt ղࠗ௏٘ ࠙ࢳ.

Slide 16

Slide 16 text

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 ౵ੌٜ੉ ࢤࢿػ׮.

Slide 17

Slide 17 text

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 ӏ஗੉ ࠁ੉աਃ?

Slide 18

Slide 18 text

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੉ ੓׮???

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

@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਷ জ੄ ੄ઓࢿ Ӓې೐ܳ ࢤࢿೞח ӝળ੉ ػ׮.

Slide 21

Slide 21 text

Bar Overview ExampleApplication DaggerExampleApplication_HiltComponents_SingletonC ExampleActivity FooModule

Slide 22

Slide 22 text

@HiltAndroidApp class ExampleApplication : Application() { @Inject lateinit var bar: Bar } Bar Overview ExampleApplication DaggerExampleApplication_HiltComponents_SingletonC ExampleActivity FooModule (1) ӝࠄ ࢤࢿغח ੄ઓࢿ Ӓې೐ܳ ࢓ಝࠁ੗.

Slide 23

Slide 23 text

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.

Slide 24

Slide 24 text

@Scope @Documented @Retention(RUNTIME) public @interface Singleton {} @Singleton @DefineComponent public interface SingletonComponent {}

Slide 25

Slide 25 text

public final class ExampleApplication_HiltComponents { @Component( modules = { ApplicationContextModule.class, ActivityRetainedCBuilderModule.class, } ) @Singleton public abstract static class SingletonC implements HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint, SingletonComponent, GeneratedComponent { } }

Slide 26

Slide 26 text

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݃׮ ੉۠ ௿ېझо ࢤࢿػ׮.

Slide 27

Slide 27 text

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ী ؀਽ೞח ௿ېझ.

Slide 28

Slide 28 text

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 ࢚ਤ ஹನք౟੄ ੄ઓࢿਸ ೞਤী ઱ੑೡ ࣻ ੓Ҋ, ৉ਵ۽ח ೡ ࣻ হ׮. যڌѱ???

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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 ) { ... } } }

Slide 31

Slide 31 text

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.

Slide 32

Slide 32 text

@Module @InstallIn(SingletonComponent::class) object FooModule { @Provides fun provideBar(): Bar = Bar() } Bar Overview ExampleApplication DaggerExampleApplication_HiltComponents_SingletonC ExampleActivity (2) ૒੽ ੿੄ೠ ੄ઓࢿ੉ Ӓې೐ী যڌѱ ୶оغח૑ ࢓ಝࠁ੗. FooModule

Slide 33

Slide 33 text

@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੉ ୶оػ׮.

Slide 34

Slide 34 text

@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 ௿ېझо ࢤࢿػ׮.

Slide 35

Slide 35 text

@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

Slide 36

Slide 36 text

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) { } }

Slide 37

Slide 37 text

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ী ੸੺൤ ୶оػ׮.

Slide 38

Slide 38 text

Hilt_ExampleApplication.java @HiltAndroidApp class ExampleApplication : Application() { @Inject lateinit var bar: Bar } = @HiltAndroidApp class ExampleApplication : Hilt_ExampleApplication() { @Inject lateinit var bar: Bar } ߄੉౟௏٘ܳ ߸ജೞৈ, ࠗݽ ௿ېझܳ ߸҃ೠ׮.

Slide 39

Slide 39 text

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ী ੽Ӕೞৈ, ੄ઓࢿ ઱ੑਸ ਃ୒ೠ׮.

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

@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 ௿ېझܳ ా೧ ੄ઓࢿਸ ઁҕೠ׮.

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

class Bar @Inject constructor() // -------------------------------------------------------------------------------- private static final class SingletonCImpl extends SingletonC { public void injectExampleApplication(ExampleApplication instance) { ExampleApplication_MembersInjector.injectBar(instance, new Bar()); } } @Injectח ߹ب੄ ௏٘হ੉, ੄ઓࢿਸ ߄۽ ઁҕೠ׮.

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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ܳ ೣԋ ࢎਊ೧ب زੌೞ׮.

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

@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ܳ ࢤࢿೠ׮.

Slide 51

Slide 51 text

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ח ё୓ܳ ೞա݅ ࢤࢿೠ׮.

Slide 52

Slide 52 text

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 }

Slide 53

Slide 53 text

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੉ ৈ۞ ߣ ࢤࢿؼ ࣻب ੓׮.

Slide 54

Slide 54 text

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ܳ ࢶ঱ೞח ਤ஖ܳ ઱੄ೞ੗!

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

@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 }

Slide 57

Slide 57 text

@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 ݃׮ ࢲ۽ ׮ܲ ё୓ܳ ࢤࢿೠ׮.

Slide 58

Slide 58 text

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() }

Slide 59

Slide 59 text

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() }

Slide 60

Slide 60 text

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()

Slide 61

Slide 61 text

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 ) { ... }

Slide 62

Slide 62 text

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()

Slide 63

Slide 63 text

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()

Slide 64

Slide 64 text

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()

Slide 65

Slide 65 text

@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о ੄ઓࢿ Ӓې೐ী ୶оػ׮.

Slide 66

Slide 66 text

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ܳ оઉৡ׮.

Slide 67

Slide 67 text

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???

Slide 68

Slide 68 text

// 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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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 ਃ્ জ਷ ӝמ੉ ݆ই૑ݶࢲ, ੼੼ ؊ ݽٕਸ ࣁ࠙ചೞҊ ੓׮.

Slide 73

Slide 73 text

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' }

Slide 74

Slide 74 text

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ਸ ੿੄ೡ ࣻ ੓׮.

Slide 75

Slide 75 text

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() ௏٘۽ח ੉۠ ഋకо ؼ ࣻ ੓׮.

Slide 76

Slide 76 text

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,

Slide 77

Slide 77 text

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,

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

App Architecture: interface, class ܻ࠙ :domain :data class ExampleUseCase @Inject constructor( private val repository: ExampleRepository ) { ... } class ExampleRepository @Inject constructor( ) { ... } ҳഅ୓ী ૒੽ ੄ઓࢿਸ ыח Ѫ ࠁ׮ח,

Slide 82

Slide 82 text

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ܳ ܻ࠙ೞৈ, ҳഅ୓ܳ ૒੽ ଵઑೞ૑ ঋب۾ ѐࢶೡ ࣻ ੓׮.

Slide 83

Slide 83 text

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 ఃਕ٘ܳ ੉ਊೡ ࣻ ੓׮.

Slide 84

Slide 84 text

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ܳ ࢤࢿೞৈ

Slide 85

Slide 85 text

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 { } }

Slide 86

Slide 86 text

App Architecture: internal ޙઁ੼ ௿ېझ݃׮ internal ఃਕ٘ܳ ୶о೧ঠ ೠ׮. (߈ࠂ ੘স) = “׮ܲ ߑߨਸ Ҋ޹೧ࠁ੗…” = ѐߊ੗о ֬஖ӝ औ׮. (पࣻ ਬߊ)

Slide 87

Slide 87 text

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ܳ بݫੋ ݽٕ۽ ੉زೠ׮ݶ???

Slide 88

Slide 88 text

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 ) { ... }

Slide 89

Slide 89 text

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 } Ӓۡ٠೧ ࠁੋ׮. بݫੋ ݽٕ੉ ೞաۄݶ…

Slide 90

Slide 90 text

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ܳ য٣ী ىঠ ೡө???

Slide 91

Slide 91 text

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 ࢎਊೞח ݽٕ۽ ৤ѹঠ ೞա???

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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 ୭ઙ੸ਵ۽ জ ݽٕ݅ ࣁࠗ ݽٕী ੽Ӕೡ ࣻ ੓ѱ ѐࢶೡ ࣻ ੓׮.

Slide 98

Slide 98 text

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 জ ݽٕب ੽Ӕೞ૑ ޅೞѱ, ੄ઓࢿ Ӓې೐ী݅ ನೣغب۾ ೡ ࣻب ੓׮.

Slide 99

Slide 99 text

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/

Slide 100

Slide 100 text

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