2

我已经基于格子应用构建了一个包含片段、子组件和依赖组件的动态功能模块示例,如果您想查看这里是链接。现在,我正在尝试使用官方 android 文档将其转换为 Dagger Hilt 。

在库模块的核心模块中,应用程序模块和动态功能模块依赖于

@Singleton
@Component(modules = [CoreModule::class])
interface CoreComponent {

    /*
        Provision methods to provide dependencies below to components that depends on
        CoreComponent
     */
    fun coreDependency(): CoreDependency

    fun coreCameraDependency(): CoreCameraDependency

    fun corePhotoDependency(): CorePhotoDependency

    fun coreActivityDependency(): CoreActivityDependency

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance application: Application): CoreComponent
    }

}

它是模块

@Module(includes = [CoreProvideModule::class])
abstract class CoreModule {
    @Binds
    abstract fun bindContext(application: Application): Context
}

@Module
object CoreProvideModule {

    @Singleton
    @Provides
    fun provideCoreDependency(application: Application) = CoreDependency(application)

    @ActivityScope
    @Provides
    fun provideCoreActivityDependency(context: Context) = CoreActivityDependency(context)

    @Provides
    fun provideCoreCameraDependency(): CoreCameraDependency = CoreCameraDependency()

    @Provides
    fun provideCorePhotoDependency(): CorePhotoDependency = CorePhotoDependency()

}

CoreComponent 是如何迁移的?提供方法是否仍然存在,我只会改变

@Singleton
@DefineComponent

或者

@Singleton
@DefineComponent(parent = ApplicationComponent.class)

对于 CoreModule 我想我只改变

@EntryPoint
@InstallIn(CoreComponent::class)

或者这是为了添加提供方法CoreComponent

如何在应用模块中创建子组件?

如果有人有一个带有动态特征片段和刀柄的示例,或者要构建的教程,那将是非常受欢迎的。我现在正在研究它,如果我弄清楚我会发布答案

4

1 回答 1

3

我终于弄明白了。

对于应用程序结构

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
}

并将component依赖项注入此 DFMFragments或其中Activities

@Component( 依赖项 = [CoreComponent::class], 模块 = [CameraModule::class] ) 接口 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
}

}

如果注入到 Activity 调用中onCreate()

  DaggerCameraComponent.factory().create(
            EntryPointAccessors.fromApplication(
                    applicationContext,
                    CoreComponent::class.java
            ),
            application
    )
            .inject(this)

用于注入 Fragment 调用onCreate()

DaggerCameraComponent.factory().create(
        EntryPointAccessors.fromApplication(
                requireActivity().applicationContext,
                CoreComponent::class.java
        ),
        requireActivity().application
)
        .inject(this)

诀窍是在这里获得@EntryPoint 使用注释的依赖接口EntryPointAccessors.fromApplication()

还在 app 模块中创建了基于 Activity 的依赖项

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

}

并且只打算将这些依赖项注入照片动态功能模块,因此将其命名为PhotoDependencies

@EntryPoint
@InstallIn(ActivityComponent::class)
interface PhotoModuleDependencies {

    fun toastMaker(): ToastMaker

    fun mainActivityObject(): MainActivityObject
}

在 Photos 动态功能模块中创建名为 dagger 的模块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
}

和组件

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

并注入碎片

DaggerPhotoComponent.factory().create(
        EntryPointAccessors.fromActivity(
                requireActivity(),
                PhotoModuleDependencies::class.java
        ),
        requireActivity().application
)
        .inject(this)

这里的诀窍是获取EntryPointAccessors.fromActivity而不是 fromApplication。

如果您想自己进行实验,可以查看此链接。

如果您希望ViewModel使用刀柄添加到动态功能模块,您可以在此处查看我的答案。

于 2020-07-22T14:34:58.700 回答