带有 Dagger Hilt 的 Android 动态功能模块

2023-12-07

我已经构建了一个动态功能模块示例,其中包含基于格子应用程序的片段、子组件和依赖组件,如果您想查看here是链接。现在,我正在尝试使用将其转换为 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

or

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

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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有 Dagger Hilt 的 Android 动态功能模块 的相关文章

随机推荐

  • 如何在 iOS (iPhone) 中使用 opencv 比较图像

    我想在我的项目中比较 iPhone 相机拍摄的 2 张图像 我正在使用 OpenCV 来做到这一点 还有其他更好的方法吗 如果我得到 相似度 那就太好了 我使用 OpenCV 以下代码进行图像比较 void opencvImageCompa
  • 找不到源中事件 ID 的描述

    当我将日志写入 Windows 事件日志时 我收到以下事件 此消息的根本原因是什么 以及如何修复它 非常感谢 事件 ID 51001 的描述 无法找到源 RRWS 引发此问题的组件 您的本地未安装事件 计算机或安装是 已损坏 您可以安装或修
  • 在android中使用AudioRecord录制立体声

    我正在寻找有关让 audioRecord 使用顶部安装和底部安装的麦克风的明确答案 因此我没有 2 个相同的 单声道 通道 我想知道我可以事先进行哪些轮询以确保小工具能够提供良好的流 我正在开发 Galaxy Nexus 5 但无法使其正常
  • 无法编译 C++ 项目(宏“max”传递了 3 个参数,但只需要 2 个)

    抱歉使用通用标题 但我不是 C 编译方面的专业人士 而且我似乎无法在这里找到错误 我正在查看一个官方项目 所以我知道该项目实际上应该可以正常编译 事实并非如此 如果有人想自己检查代码 请执行以下操作 cvs d pserver jvtuse
  • 在每个请求上使用基于角色的自定义身份验证查询数据库的正确方法 ASP.NET MVC

    这可能是一个有点无知的问题 但我是 mvc 新手 所以我很抱歉 我研究了书呆子晚餐身份验证模型 但在我的应用程序中 我有一个复杂的基于角色的身份验证 所以我做的是这样的 void MvcApplication PostAuthenticat
  • 安装 Spark 2.4.4 后尝试运行 pyspark 时如何修复“TypeError:需要一个整数(获取类型字节)”错误

    我已经安装了 OpenJDK 13 0 1 和 python 3 8 和 Spark 2 4 4 测试安装的说明是从 Spark 安装的根目录运行 bin pyspark 我不确定我是否错过了 Spark 安装中的某个步骤 例如设置一些环境
  • 对列表进行子集化(为所有组件选择匹配值)

    我尝试以某种方式从列表中读出某些元素 这相当于df c 1 4 5 in a data frame gt obj lt list c 1 5 c 1 5 gt obj 1 1 1 2 3 4 5 2 1 1 2 3 4 5 我正在寻找这样的
  • 为什么ACTION_MEDIA_BUTTON无法处理事件?

    遵循有关如何进行的培训部分使用硬件播放控制键来控制音频播放 我创建一个监听器类 public class RemoteControlReceiver extends BroadcastReceiver Override public voi
  • CMake:对 boost 库的未定义引用

    我通过这个添加了提升 set Boost USE STATIC LIBS ON set Boost USE MULTITHREADED ON set Boost USE STATIC RUNTIME OFF find package Boo
  • 我一直搞砸 1NF

    对我来说 到目前为止我发现的关于 1NF 最容易理解的描述是 主键是唯一标识每一行的一列 或一组列 在 www phlonx com 上 据我所知 冗余意味着每个键每行的值不应超过 1 个 超过 1 的值将是 冗余的 正确的 尽管如此 我还
  • Javascript Array.sort 实现?

    JavaScript 使用哪种算法Array sort 功能使用 我知道它可以采用各种方式的参数和函数来执行不同类型的排序 我只是对普通排序使用哪种算法感兴趣 我刚刚浏览了 WebKit Chrome Safari source 根据数组的
  • Java:空间对编译有影响吗?

    我正在制作一个程序 有点像 Piglatin 其中我无意中错过了语句中的一个变量 String a R a 其实应该是String a R text a 编译器产生了一个错误 但是 当我做到了 String a R a 程序编译完成 我想知
  • 需要在导航抽屉内显示可扩展列表视图

    I am an Android Application Developer I have started working on React Native I am unable to find a way to show expandabl
  • ASP.NET MVC 5 身份 userManager.IsInRole

    以下代码不起作用 我无法解释为什么 我的用户管理器造成了很大的困扰 因为它创建用户和角色很好 但是当我运行此代码时 userManager IsInRole 总是返回 false 所以第二个当我运行我的种子时 我遇到了错误 因为它试图创建记
  • Zend Framework 2 库路径

    当我试图尝试 ZF2 时 我偶然发现了我的第一个问题 在模块上说我想使用 Shanty Mongo 连接到 MongoDb 的外部库 因此 我复制了库上的整个 Shanty 目录并创建了一个新的 Model 类 namespace Dumm
  • AsyncTask不能在android线程中工作

    我使用 AsyncTask 来更改 TextView 的文本 如下所示 private class LongOperation extends AsyncTask
  • Twisted:重新连接ClientFactory连接到不同的服务器

    我有一个扭曲的 ReconnectingClientFactory 我可以通过该工厂成功连接到给定的 ip 和端口 而且效果很好 reactor connectTCP ip 端口 myHandsomeReconnectingClientFa
  • 如何找到与我的代码兼容的所有以前版本的 python

    我在 python 2 7 3 中创建了一个中型项目 包含大约 100 个模块 我希望找出我的代码与哪些以前版本的 python 例如 2 6 x 2 7 x 兼容 在公共领域发布我的项目之前 找到它的最简单方法是什么 我知道的解决方案 安
  • 使用索引作为键初始化对象数组[重复]

    这个问题在这里已经有答案了 我试图找出如何初始化一个对象数组 其中每个对象都以索引 i 作为其键 以 0 作为其值 下面的代码没有按预期工作 但我不明白为什么 我还是 Javascript 的初学者 在其他地方找不到答案 var n 10
  • 带有 Dagger Hilt 的 Android 动态功能模块

    我已经构建了一个动态功能模块示例 其中包含基于格子应用程序的片段 子组件和依赖组件 如果您想查看here是链接 现在 我正在尝试使用将其转换为 Dagger Hilt安卓官方文档 在核心模块中 即库模块 应用程序模块和动态功能模块依赖于 S