簡體   English   中英

Android 帶匕首刀柄的動態功能模塊

[英]Android Dynamic Feature modules with Dagger Hilt

我已經基於格子應用構建了一個包含片段、子組件和依賴組件的動態功能模塊示例,如果您想查看這里是鏈接。 現在,我正在嘗試使用官方 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中添加提供方法?

如何在應用模塊中創建子組件?

如果有人有一個帶有動態特征片段和刀柄的示例,或者要構建的教程,那將是非常受歡迎的。 我現在正在研究它,如果我弄清楚我會發布答案

我終於弄明白了。

對於應用程序結構

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
}

以及向此 DFM 中的FragmentsActivities注入依賴項的component

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

}

如果在onCreate()中注入 Activity 調用

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

用於在onCreate()中注入 Fragment 調用

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

訣竅是使用EntryPointAccessors.fromApplication()獲得用@EntryPoint注釋的依賴接口

還在 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
}

在照片動態功能模塊中創建名為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添加到帶有刀柄的動態功能模塊中,您可以在此處查看我的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM