简体   繁体   English

Android 带匕首刀柄的动态功能模块

[英]Android Dynamic Feature modules with Dagger Hilt

I have built a Dynamic feature module sample with Fragments, sub components and dependent components based on plaid app, if you wish to check out here is the link.我已经基于格子应用构建了一个包含片段、子组件和依赖组件的动态功能模块示例,如果您想查看这里是链接。 Now, i'm trying to convert it to Dagger Hilt using the official android document .现在,我正在尝试使用官方 android 文档将其转换为 Dagger Hilt。

In core module which is the library module, app module and dynamic feature modules depend on在库模块的核心模块中,应用程序模块和动态功能模块依赖于

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

}

and it's module它是模块

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

}

How is CoreComponent migrated? CoreComponent 是如何迁移的? Do provision methods still stay and i only change提供方法是否仍然存在,我只会改变

@Singleton
@DefineComponent

or或者

@Singleton
@DefineComponent(parent = ApplicationComponent.class)

for CoreModule i guess i only change对于 CoreModule 我想我只改变

@EntryPoint
@InstallIn(CoreComponent::class)

or is this for adding provision methods in CoreComponent ?或者这是为了在CoreComponent中添加提供方法?

How do i create sub-component in app module?如何在应用模块中创建子组件?

If anyone has a sample with dynamic feature fragments and hilt, or tutorial to build, it would be more than welcome.如果有人有一个带有动态特征片段和刀柄的示例,或者要构建的教程,那将是非常受欢迎的。 I'm just working on it at the moment, if i figure it out i would post an answer我现在正在研究它,如果我弄清楚我会发布答案

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首先在库模块中创建一个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()
}

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.带有@EntryPoint的接口需要在此接口中定义提供方法,如果您没有为该依赖项定义方法,即使有@Provides方法,您也无法注入它。 These are mock dependencies that take application or context as only parameter.这些是将应用程序或上下文作为唯一参数的模拟依赖项。

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

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.以及向此 DFM 中的FragmentsActivities注入依赖项的component

@Component( dependencies = [CoreComponent::class], modules = [CameraModule::class] ) interface CameraComponent { @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
}

} }

If injected to Activity call in onCreate()如果在onCreate()中注入 Activity 调用

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

For injecting to Fragment call in onCreate()用于在onCreate()中注入 Fragment 调用

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()诀窍是使用EntryPointAccessors.fromApplication()获得用@EntryPoint注释的依赖接口

Also created Activity based dependencies in app module还在 app 模块中创建了基于 Activity 的依赖项

MainActivityModule.kt 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并且只打算将这些依赖项注入照片动态功能模块,因此将其命名为PhotoDependencies

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

    fun toastMaker(): ToastMaker

    fun mainActivityObject(): MainActivityObject
}

In Photos dynamic feature module create dagger module named PhotoModule在照片动态功能模块中创建名为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.这里的技巧是获取EntryPointAccessors.fromActivity而不是 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 .如果您希望将ViewModel添加到带有刀柄的动态功能模块中,您可以在此处查看我的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM