我终于弄明白了。
对于应用程序结构
FeatureCamera FeaturePhotos (Dynamic Feature Modules)
| | |
| ----App
| |
core(android-library)
相机动态功能模块依赖于核心模块,照片动态功能模块依赖于应用程序。
首先创建一个CoreModule
在库模块中
@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()
}
一个接口@EntryPoint
需要在此接口中定义提供方法,如果您没有为该依赖项定义方法,则即使有一个也无法注入它@Provides
的方法。这些是模拟依赖项,将应用程序或上下文作为唯一参数。
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface CoreComponent {
/*
Provision methods to provide dependencies to components that depend on this component
*/
fun coreDependency(): CoreDependency
fun coreActivityDependency(): CoreActivityDependency
fun coreCameraDependency(): CoreCameraDependency
fun corePhotoDependency(): CorePhotoDependency
}
在相机动态功能模块中,为此动态功能模块内部基于依赖关系创建另一个模块。
@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
注入依赖项Fragments
or Activities
在这个 DFM 中。
@Component(
dependencies = [CoreComponent::class],
modules = [CameraModule::class]
)
interface CameraComponent {
fun inject(cameraFragment1: CameraFragment1)
fun inject(cameraFragment2: CameraFragment2)
fun inject(cameraActivity: CameraActivity)
@Component.Factory
interface Factory {
fun create(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)
interface PhotoModuleDependencies {
fun toastMaker(): ToastMaker
fun mainActivityObject(): 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]
)
interface PhotoComponent {
fun inject(photosFragment1: PhotoFragment1)
fun inject(photosFragment2: PhotoFragment2)
@Component.Factory
interface Factory {
fun create(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][1] 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][2].
[1]: https://github.com/SmartToolFactory/Dagger2-Tutorials/tree/master/Tutorial10-1DFM-DaggerHilt
[2]: https://stackoverflow.com/questions/63671489/how-to-create-viewmodel-in-dynamic-feature-module-with-dagger-hilt