Android Dynamic Feature Modules With Dagger Hilt
Solution 1:
I finally figured it out.
For an app structure
FeatureCamera FeaturePhotos (Dynamic Feature Modules)
||||----App||
core(android-library)
Camera dynamic feature module dependencies from core module, Photo dynamic feature module dependencies from app.
First create a CoreModule
in library module
@InstallIn(ApplicationComponent::class)
@Module
class CoreModule {
@Singleton@Provides
fun provideCoreDependency(application: Application) = CoreDependency(application)
@Provides
fun provideCoreActivityDependency(context: Application) = CoreActivityDependency(context)
@Provides
fun provideCoreCameraDependency(): CoreCameraDependency = CoreCameraDependency()
@Provides
fun provideCorePhotoDependency(): CorePhotoDependency = CorePhotoDependency()
}
An interface with @EntryPoint
is required to with provision methods defined in this interface, if you don't define a method for that dependency you cannot inject it even though there is a @Provides
method for it. These are mock dependencies that take application or context as only parameter.
@EntryPoint@InstallIn(ApplicationComponent::class)interfaceCoreComponent{
/*
Provision methods to provide dependencies to components that depend on this component
*/funcoreDependency(): CoreDependency
funcoreActivityDependency(): CoreActivityDependency
funcoreCameraDependency(): CoreCameraDependency
funcorePhotoDependency(): CorePhotoDependency
}
In camera dynamic feature module, create another module for the dependency based inside of this dynamic feature module.
@InstallIn(FragmentComponent::class)
@Module(includes = [CameraBindModule::class])
class CameraModule {
@Provides
fun provideCameraObject(context: Context) = CameraObject(context)
}
@InstallIn(FragmentComponent::class)
@Module
abstract class CameraBindModule {
@Binds
abstract fun bindContext(application: Application): Context
}
And component
to inject dependencies to Fragments
or Activities
in this DFM.
@Component( dependencies = [CoreComponent::class], modules = [CameraModule::class] ) interface CameraComponent {
funinject(cameraFragment1: CameraFragment1)funinject(cameraFragment2: CameraFragment2)funinject(cameraActivity: CameraActivity)@Component.Factory
interfaceFactory{
funcreate(coreComponent: CoreComponent, @BindsInstance application: Application): CameraComponent
}
}
If injected to Activity call in onCreate()
DaggerCameraComponent.factory().create(
EntryPointAccessors.fromApplication(
applicationContext,
CoreComponent::class.java
),
application
)
.inject(this)
For injecting to Fragment call in onCreate()
DaggerCameraComponent.factory().create(
EntryPointAccessors.fromApplication(
requireActivity().applicationContext,
CoreComponent::class.java
),
requireActivity().application
)
.inject(this)
The trick is here to get dependency interface annotated with @EntryPoint
using EntryPointAccessors.fromApplication()
Also created Activity based dependencies in app module
MainActivityModule.kt
@InstallIn(ActivityComponent::class)
@Module(includes = [MainActivityBindModule::class])
class MainActivityModule {
@Provides
fun provideToastMaker(application: Application) = ToastMaker(application)
@ActivityScoped@Provides
fun provideMainActivityObject(context: Context) = MainActivityObject(context)
}
@InstallIn(ActivityComponent::class)
@Module
abstract class MainActivityBindModule {
@Binds
abstract fun bindContext(application: Application): Context
}
And only intend to inject these dependencies to Photos dynamic feature module so named it as PhotoDependencies
@EntryPoint@InstallIn(ActivityComponent::class)interfacePhotoModuleDependencies{
funtoastMaker(): ToastMaker
funmainActivityObject(): MainActivityObject
}
In Photos dynamic feature module create dagger module named PhotoModule
@InstallIn(FragmentComponent::class)
@Module(includes = [PhotoBindModule::class])
class PhotoModule {
@Provides
fun providePhotoObject(application: Application): PhotoObject = PhotoObject(application)
}
@InstallIn(FragmentComponent::class)
@Module
abstract class PhotoBindModule {
@Binds
abstract fun bindContext(application: Application): Context
}
And component
@Component(
dependencies = [PhotoModuleDependencies::class],
modules = [PhotoModule::class]
)interfacePhotoComponent{
funinject(photosFragment1: PhotoFragment1)funinject(photosFragment2: PhotoFragment2)@Component.Factory
interfaceFactory{
funcreate(photoModuleDependencies: PhotoModuleDependencies,
@BindsInstance application: Application): PhotoComponent
}
}
And inject to fragments with
DaggerPhotoComponent.factory().create(
EntryPointAccessors.fromActivity(
requireActivity(),
PhotoModuleDependencies::class.java
),
requireActivity().application
)
.inject(this)
The trick here is to get EntryPointAccessors.fromActivity
instead of fromApplication.
You can check out this link if you wish to experiment yourself.
If you wish to add ViewModel
to dynamic feature modules with hilt you can check out my answer here.
Post a Comment for "Android Dynamic Feature Modules With Dagger Hilt"