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

Hilt Annotation 뜯어보기

Hilt Annotation 뜯어보기

Mash-Up 14기 안드로이드팀 10분 세미나 : Hilt Annotation 뜯어보기

Avatar for Jaesung Lee

Jaesung Lee

August 21, 2025
Tweet

More Decks by Jaesung Lee

Other Decks in Programming

Transcript

  1. 필요 기반 지식 Session Team Name 1. DI가 무엇인지 이해하고

    있다. 2. DI 라이브러리로 Hilt를 사용한 경험이 있다. 3. Hilt의 기본적인 특징에 대해 이해하고 있다.
  2. Session Android Team Hilt_MooBesideApplication.java Hilt가 generate code를 생성하는 방식 @HiltAndroidApp

    @HiltViewModel MooBesideApplication_GeneratedInjector.java MooBesideApplication_HiltComponents.java HomeViewModel_HiltModules.java HomeViewModel_HiltModules_KeyModule _ProvideFactory.java DaggerMooBesideApplication _HiltComponents_SingletonC.java HomeViewModel_Factory.java
  3. @HiltAndroidApp Session @HiltAndroidApp class MooBesideApplication : Application() // ======================= Generate

    by Hilt ============================= @Generated("dagger.hilt.processor.internal.root.RootProcessor") public final class MooBesideApplication_HiltComponents { ... @Component(modules = { ApplicationContextModule.class, DatabaseModule.class, DispatcherModule.class, ... }) @Singleton public abstract static class SingletonC implements MooBesideApplication_GeneratedInjector, FragmentGetContextFix.FragmentGetContextFixEntryPoint, HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint, ServiceComponentManager.ServiceComponentBuilderEntryPoint, SingletonComponent, GeneratedComponent { } } Android Team
  4. @HiltAndroidApp Session @HiltAndroidApp class MooBesideApplication : Application() // ======================= Generate

    by Hilt ============================= @Generated("dagger.hilt.processor.internal.root.RootProcessor") public final class MooBesideApplication_HiltComponents { ... @Component(modules = { ApplicationContextModule.class, DatabaseModule.class, DispatcherModule.class, ... }) @Singleton public abstract static class SingletonC implements MooBesideApplication_GeneratedInjector, FragmentGetContextFix.FragmentGetContextFixEntryPoint, HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint, ServiceComponentManager.ServiceComponentBuilderEntryPoint, SingletonComponent, GeneratedComponent { } } Android Team
  5. @HiltAndroidApp Session // DaggerMooBesideApplication_HiltComponents_SingletonC.java // ============================== Generate by Dagger ==============================

    private static final class SingletonCImpl extends MooBesideApplication_HiltComponents.SingletonC { private final DatabaseModule databaseModule; ... @Override public void injectMooBesideApplication(MooBesideApplication mooBesideApplication) { injectMooBesideApplication2(mooBesideApplication); } } Android Team
  6. @HiltAndroidApp Session @Generated("dagger.hilt.android.processor.internal.androidentrypoint.ApplicationGenerator") public abstract class Hilt_MooBesideApplication extends Application implements

    GeneratedComponentManagerHolder { private boolean injected = false; private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() { @Override public Object get() { return DaggerMooBesideApplication_HiltComponents_SingletonC.builder() .applicationContextModule(new ApplicationContextModule(Hilt_MooBesideApplication.this)) .build(); } }); ... } Android Team
  7. @HiltAndroidApp Session @Generated("dagger.hilt.android.processor.internal.androidentrypoint.ApplicationGenerator") public abstract class Hilt_MooBesideApplication extends Application implements

    GeneratedComponentManagerHolder { .. @CallSuper @Override public void onCreate() { hiltInternalInject(); super.onCreate(); } protected void hiltInternalInject() { if (!injected) { injected = true; ((MooBesideApplication_GeneratedInjector) componentManager.generatedComponent()) .injectMooBesideApplication(UnsafeCasts.<MooBesideApplication>unsafeCast(this)); } } } Android Team
  8. @HiltAndroidApp Session Android Team @Generated("dagger.hilt.android.processor.internal.androidentrypoint.ApplicationGenerator") public abstract class Hilt_MooBesideApplication extends

    Application implements GeneratedComponentManagerHolder { .. @CallSuper @Override public void onCreate() { hiltInternalInject(); super.onCreate(); } protected void hiltInternalInject() { if (!injected) { injected = true; ((MooBesideApplication_GeneratedInjector) componentManager.generatedComponent()) .injectMooBesideApplication(UnsafeCasts.<MooBesideApplication>unsafeCast(this)); } } }
  9. @HiltViewModel Session 뷰모델에 대한 의존성을 주입하기 위해 사용하는 Hilt Annotation

    @AndroidEntryPoint로 선언된 Activity/Fragment에서 사용이 뷰모델 인스턴스 사용이 가능해짐 Android Team
  10. 기존 ViewModel 생성 방식 Session Android Team class MainActivity :

    AppCompatActivity() { private val viewModel: MainViewModel by lazy { ViewModelProvider(this, object : ViewModelProvider.Factory { override fun <T : ViewModel?> create(modelClass: Class<T>): T { return MainViewModel() as T } }).get(MainViewModel::class.java) } // ... }
  11. Dagger에서 ViewModel 생성 방식 Session Android Team class ViewModelFactory @Inject

    constructor( private val providerMap: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>> ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create(modelClass: Class<T>): T { return providerMap[modelClass]!!.get() as T } } @MapKey annotation class ViewModelKey(val key: KClass<out ViewModel>)
  12. Dagger에서 ViewModel 생성 방식 Session Android Team class ViewModelFactory @Inject

    constructor( private val providerMap: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>> ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create(modelClass: Class<T>): T { return providerMap[modelClass]!!.get() as T } } @MapKey annotation class ViewModelKey(val key: KClass<out ViewModel>)
  13. Dagger에서 ViewModel 생성 방식 Session Android Team @Module abstract class

    ViewModelFactoryModule { @Binds abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory } @Module abstract class ViewModelModule { @Binds @IntoMap @ViewModelKey(MainViewModel::class) abstract fun bindMainViewModel(viewModel: MainViewModel): ViewModel @Binds @IntoMap @ViewModelKey(SecondViewModel::class) abstract fun bindSecondViewModel(viewModel: SecondViewModel): ViewModel }
  14. Dagger에서 ViewModel 생성 방식 Session Android Team @Module abstract class

    ViewModelFactoryModule { @Binds abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory } @Module abstract class ViewModelModule { @Binds @IntoMap @ViewModelKey(MainViewModel::class) abstract fun bindMainViewModel(viewModel: MainViewModel): ViewModel @Binds @IntoMap @ViewModelKey(SecondViewModel::class) abstract fun bindSecondViewModel(viewModel: SecondViewModel): ViewModel }
  15. Dagger에서 ViewModel 생성 방식 Session Android Team class MainActivity :

    AppCompatActivity() { @Inject val viewModelFactory: ViewModelProvider.Factory private val viewModel: MainViewModel by viewModels({ viewModelFactory }) }
  16. @HiltViewModel Session Android Team @Generated("dagger.hilt.android.processor.internal.viewmodel.ViewModelProcessor") @OriginatingElement(topLevelClass = HomeViewModel.class) public final

    class HomeViewModel_HiltModules { private HomeViewModel_HiltModules() { } @Module @InstallIn(ViewModelComponent.class) public abstract static class BindsModule { private BindsModule() { } @Binds @IntoMap @StringKey("com.jslee.presentation.feature.home.HomeViewModel") @HiltViewModelMap public abstract ViewModel binds(HomeViewModel vm); } .. }
  17. by viewModels Session Android Team @MainThread public inline fun <reified

    VM : ViewModel> ComponentActivity.viewModels( noinline extrasProducer: (() -> CreationExtras)? = null, noinline factoryProducer: (() -> Factory)? = null ): Lazy<VM> { val factoryPromise = factoryProducer ?: { defaultViewModelProviderFactory } return ViewModelLazy( VM::class, { viewModelStore }, factoryPromise, { extrasProducer?.invoke() ?: this.defaultViewModelCreationExtras } ) }
  18. by viewModels Session Android Team public abstract class Hilt_MainActivity<VB extends

    ViewDataBinding> extends BaseActivity<VB> implements GeneratedComponentManagerHolder { ... @Override public ViewModelProvider.Factory getDefaultViewModelProviderFactory() { return DefaultViewModelFactories.getActivityFactory(this, super.getDefaultViewModelProviderFactory()); } }
  19. @HiltViewModel Session Android Team public final class DefaultViewModelFactories { public

    static ViewModelProvider.Factory getActivityFactory(ComponentActivity activity, ViewModelProvider.Factory delegateFactory) { return EntryPoints.get(activity, ActivityEntryPoint.class) .getHiltInternalFactoryFactory() .fromActivity(activity, delegateFactory); } .. ViewModelProvider.Factory fromActivity( ComponentActivity activity, ViewModelProvider.Factory delegateFactory) { return getHiltViewModelFactory( activity, activity.getIntent() != null ? activity.getIntent().getExtras() : null, delegateFactory); } }
  20. @HiltViewModel Session Android Team public final class DefaultViewModelFactories { public

    static ViewModelProvider.Factory getActivityFactory(ComponentActivity activity, ViewModelProvider.Factory delegateFactory) { return EntryPoints.get(activity, ActivityEntryPoint.class) .getHiltInternalFactoryFactory() .fromActivity(activity, delegateFactory); } .. ViewModelProvider.Factory fromActivity( ComponentActivity activity, ViewModelProvider.Factory delegateFactory) { return getHiltViewModelFactory( activity, activity.getIntent() != null ? activity.getIntent().getExtras() : null, delegateFactory); } }
  21. @HiltViewModel Session Android Team public final class DefaultViewModelFactories { public

    static ViewModelProvider.Factory getActivityFactory(ComponentActivity activity, ViewModelProvider.Factory delegateFactory) { return EntryPoints.get(activity, ActivityEntryPoint.class) .getHiltInternalFactoryFactory() .fromActivity(activity, delegateFactory); } .. ViewModelProvider.Factory fromActivity( ComponentActivity activity, ViewModelProvider.Factory delegateFactory) { return getHiltViewModelFactory( activity, activity.getIntent() != null ? activity.getIntent().getExtras() : null, delegateFactory); } }
  22. 정리 Session @HiltViewModel @HiltAndroidApp 의존성 그래프를 생성하는 기준이 되는 Hilt

    Annotation Application#onCreate 시점에 의존성을 주입한다. 뷰모델에 대한 의존성을 주입하기 위해 사용하는 Hilt Annotation @AndroidEntryPoint로 선언된 Activity/Fragment에서 사용이 뷰모델 인스턴스 사용이 가능해짐 HiltViewModelFactory를 통해 @HiltViewModel 이 붙은 뷰모델을 반환한다. Android Team