前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >提示[译] 依赖注入在多模块工程中的应用

提示[译] 依赖注入在多模块工程中的应用

作者头像
Android 开发者
发布于 2019-06-02 13:44:15
发布于 2019-06-02 13:44:15
1.8K00
代码可运行
举报
文章被收录于专栏:Android 开发者Android 开发者
运行总次数:0
代码可运行

Plaid 应用中引入一个 DI 框架过程中我们学到的东西

总的来说,这不是一篇关于依赖注入的文章,也不是关于我们为什么选择库 X 而不是库 Y 的文章。 相反的,本文从依赖注入的角度介绍了我们对 Plaid 进行模块化实践的主要成果。

我们的设置

在前面的文章中,我写过 Plaid 应用模块化的整体过程。 一款拼接应用 Plaid — 整体到模块化: 模块化 Plaid 应用的初衷、过程和结果

让我以鸟瞰图的形式快速回顾一下 Plaid 的样子。

我们有一个包含主启动 activity 的 app 模块,同时也有一些依赖 app 模块的动态功能模块(DFM)。每一个 DFM 都包含至少一个与所讨论功能相关的 activity、代码和资源。

app 模块依赖一个包含了共享的代码和资源以及第三方库的 core 模块。

在我们开始模块化操作和以 Dagger 为主介绍依赖注入之前,先来熟悉下 Plaid 的相关类和函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class DesignerNewsInjector {

    fun providesApi(...): DesignerNewsService { ... }

}
复制代码

虽然这是一个非常好的解决方案,但我们还是手工编写了大量的样板代码。

在任何需要注入的地方,我们都需要在合适的时机调用底层函数,大多数情况下不是在对象初始化时就是在 onCreate 方法中。

依赖注入的简要介绍

依赖注入基本上意味着你不用在你需要的地方创建它们,而是在别的地方创建。然后这些对象的引用可以被传递到需要使用它们的类中。

这点可以通过自己编写或者集成某个依赖注入库来实现,我们选择了集成 Dagger 2。多亏了 Dagger,为了获取一个可以使用的已初始化的 service,我们所有要做的就是如下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Inject lateinit var service: DesignerNewsService
复制代码

所有对 service 的依赖可以变成 provides 函数的传参。我们为依赖注入需求选择了 Dagger 意味着我们的依赖图在编译阶段会被创建。下面的章节中要记住这一点。

我们在 Plaid 应用中集成 Dagger 的方式

当我们决定引入 Dagger 到 Plaid 应用时,我们已经学到了宝贵的一课,尤其是对模块化。

不要试图一次就覆盖太多内容。

这意味着花一些时间研究清楚实现一个新功能的最小必要范围是有意义的。我们接下来要讨论的 MVP,即在团队内部审视我们是否在向着正确的方向前进。坚持这种做法可以防止我们进行太大而无法高效利用的变更。这也允许我们在整个代码库中逐步推出更改,与此同时每个人的任务也可持续进行。

在 Plaid 应用内我们使用已验证后的 about 功能模块作为 Dagger 的练习模块。这里我们可以添加 Dagger 而不会干扰到其他模块或负载。你可以在这里查看初始提交

依赖图解

当为一个单块应用引入依赖注入库时,通常整个应用有个单一的依赖图。

这可以使组件间共享依赖。在一些库中,依赖可以被设置作用域来避免冲突,或者为被注入对象提供一种特殊的实现。

模块化的怪异之处

对一个模块化的应用,尤其是使用动态功能模块的应用这却不起作用。让我们仔细地研究下应用和动态功能模块如何彼此依赖。一个动态功能模块知道 application 模块的存在。application 模块大致知道动态功能模块的存在,但是不能直接执行该模块的代码。对于依赖注入,这意味着整体图必须被分解成片。

对一个模块化应用,简单的依赖图通常大致长成下面这样。

更具体的是,Plaid 中组件规划图看起来像这样。

每个 DFM 都有它自己的组件,以组件所在的功能模块命名。app 模块中的 HomeComponent 组件就是如此。

还有一个包含共享依赖项的组件,它位于 core 库中并被称作 CoreComponentCoreComponent 背后的主要思想是提供可被整个应用使用的对象。它结合了一些 Dagger 模块,这些模块位于 core 库并可以在整个应用中复用。

此外,由于依赖图具有方向性,因此只能通过以下方式共享 Dagger 组件: DFM 图可以从 application 模块来访问 Dagger 组件。application 模块可以从它依赖的库中访问组件,但方向反过来则不行。

跨模块边界共享组件

为了共享 Dagger 组件,它们需要被整个应用访问到。在 Plaid 中我们决定使用 Application 类来让我们的 CoreComponent 变得可访问。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class PlaidApplication : Application() {

  private val coreComponent: CoreComponent by lazy {
    DaggerCoreComponent
      .builder()
      .markdownModule(MarkdownModule(resources.displayMetrics))
      .build()
  }

  companion object {

    @JvmStatic fun coreComponent(context: Context) =
      (context.applicationContext as PlaidApplication).coreComponent
  }
}
复制代码

被实例化的 CoreComponent 组件现在可以从应用中任何具有 context 的地方来访问,通过调用 PlaidApplication.coreComponent(context) 的方式。

使用一个扩展函数可以使 this 更好地访问:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fun Activity.coreComponent() = PlaidApplication.coreComponent(this)
复制代码

组件中的组件

为了把 CoreComponent 包含到另一个组件中,有必要在组件创建时提供它。让我们看一下在 SearchComponent` 中是如何做到的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component(modules = [...], dependencies = [CoreComponent::class])
interface SearchComponent {

  @Component.Builder
  interface Builder {

    fun coreComponent(coreComponent: CoreComponent): Builder
    // modules
  }
}
复制代码

在生成的 DaggerSearchComponent 做初始化时我们像这样设置了 CoreComponent

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DaggerSearchComponent.builder()
  .coreComponent(activity.coreComponent())
  // modules
  .build()
.inject(activity)
复制代码

这里的技巧是把 CoreComponent 设置为 SearchComponent 的一个依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component(
    modules = [SearchModule::class],
    dependencies = [CoreComponent::class]
)
interface SearchComponent : BaseActivityComponent<SearchActivity>
复制代码

CoreComponentSearchComponent 的一个依赖。当 CoreComponent 像上面那样被引用为 SearchComponent 的一个组件依赖时,所有的 CoreComponent 方法可以在 SearchComponent 中使用,或者在其他 Dagger 组件中使用,就好像他们变成注解 @Provides 标记的方法。

这样做的的一个好处是:在功能图中无需重复 @Modules ,却可以通过 CoreComponent 或其他与之绑定的模块来透明地提供出去。

例如,CoreDataModule 绑定在 CoreComponent 中,并提供 Retrofit 等。Retrofit 实例现在可以被任何与 CoreComponent 合并的组件访问到。

下一步要做什么

读完这篇文章,你可以看到模块化你的应用需要把依赖注入考虑进去。引入的功能模块边界通过分离的依赖图反映在依赖注入中。意识到这个限制可有助于为共享组件找到合适的位置。

你可以深入到代码中来查看我们如何使用 Dagger 解决 Plaid 中的依赖注入问题。

CoreComponent 是一个好的阅读开端,AboutComponent 也是,因为它没有太多的外部依赖。

如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年05月29日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
带你了解Android Jetpack库中的依赖注入框架:Hilt
Hilt是Google推出的一种用于Android的依赖注入(Dependency Injection,DI)框架,构建于Dagger之上,旨在简化Android应用中的依赖注入过程。通过Hilt,你可以更轻松地管理和提供依赖,显著减少DI的样板代码,并提高应用的可测试性和可维护性。
AntDream
2024/09/13
2070
带你了解Android Jetpack库中的依赖注入框架:Hilt
Android技术栈(三)依赖注入技术的探讨与实现
首先先给出结论。控制反转是一种软件设计思想,它被设计出来用于降低代码之间的耦合,而依赖注入是用来实现控制反转最常见的手段。
Android技术干货分享
2019/04/18
8340
Android技术栈(三)依赖注入技术的探讨与实现
从 Dagger 到 Hilt,谷歌为何执着于让我们用依赖注入?
说到依赖注入,做 Android 的人都会想到一个库:Dagger;说到 Dagger,大家的反应普遍是一套三连:牛逼、高端、我才不用。
扔物线
2020/07/31
1.5K0
从 Dagger 到 Hilt,谷歌为何执着于让我们用依赖注入?
[译] 依赖注入在多模块工程中的应用
总的来说,这不是一篇关于依赖注入的文章,也不是关于我们为什么选择库 X 而不是库 Y 的文章。 相反的,本文从依赖注入的角度介绍了我们对 Plaid 进行模块化实践的主要成果。
Android 开发者
2022/09/20
1.8K0
[译] 依赖注入在多模块工程中的应用
Dagger Android支持库(译文)
与其他依赖注入框架相比,Dagger 2 最大的优点是他不使用反射,严格的生成实现类,这意味着他可以使用在 Android 应用上。但是在Android上使用仍有一些注意事项。
haifeiWu
2018/09/11
9850
快刀斩乱码—— Dagger2没有想象的那么难
前言 本篇文章是读者『sososeen09』的投稿,Android群英传刚刚开放投稿,有什么好的建议和意见,还请大家多多和我交流,继续欢迎大家多多投稿~ 本篇文章讲解的是Dagger2,相信很多开发者对它都并不陌生,我们公司的内部分享,也有同事介绍过Dagger2。这篇文章并不是讲解Dagger2的基础使用,而是通过讲解它的使用以及套路,帮助大家更好的理解如何高效的使用Dagger2,相信大家看完,一定会对Dagger2的理解更加深刻! 谷歌开发维护的Dagger2出来有很长时间了,目前在很多开源项
用户1907613
2018/07/20
1.1K0
把 "格子衫" 改造得更时尚 | Kotlin &amp; Jetpack 最佳实践技巧
Plaid 是格子图案的意思,也是一款在 2015 年开源的 Material Design 样例应用。它通过 API 调用聚合了 Dribbble、Designer News 和 Product Hunt 三个网站的内容数据,并通过丰富的 UI 交互体验呈现给用户。
Android 开发者
2022/09/21
4480
把 "格子衫" 改造得更时尚 | Kotlin &amp; Jetpack 最佳实践技巧
把 "格子衫" 改造得更时尚 | Kotlin & Jetpack 最佳实践技巧
Plaid 是格子图案的意思,也是一款在 2015 年开源的 Material Design 样例应用。它通过 API 调用聚合了 Dribbble、Designer News 和 Product Hunt 三个网站的内容数据,并通过丰富的 UI 交互体验呈现给用户。
Android 开发者
2019/10/12
8540
把 "格子衫" 改造得更时尚 | Kotlin & Jetpack 最佳实践技巧
2018年10月9日 Go生态洞察:Go Cloud的Wire与编译时依赖注入
各位云技术爱好者,我是猫头虎博主。今天我们将深入探讨Go Cloud项目中的一个关键组件——Wire,一个在编译时进行依赖注入的强大工具。本文将详细介绍Wire的工作原理、优势及其在Go Cloud中的重要性。如果你是Go语言或云开发的热爱者,那么这篇文章绝对不容错过!🚀
猫头虎
2024/04/08
1080
2018年10月9日 Go生态洞察:Go Cloud的Wire与编译时依赖注入
Android 之dragger使用
1、依赖的注入和配置独立于组件之外,注入的对象在一个独立、不耦合的地方初始化,这样在改变注入对象时,我们只需要修改对象的实现方法,而不用大改代码库。 2、依赖可以注入到一个组件中:我们可以注入这些依赖的模拟实现,这样使得测试更加简单。 3、app中的组件不需要知道有关实例创建和生命周期的任何事情,这些由我们的依赖注入框架管理的。 我觉得,dagger2这样的依赖注入框架对MVP架构来说,是最好的解耦工具,可以进一步降低modle-view-presenter之间的耦合度。 所以,如果你的项目在使用MVP架构
xiangzhihong
2018/02/02
9870
Android 之dragger使用
Jetpack新成员,一篇文章带你玩转Hilt和依赖注入
虽然今年的Google I/O大会由于疫情的原因没能开成,但是Google每年要发布的各种新技术可一样都没少。
用户1158055
2020/11/26
2.6K0
Jetpack新成员,一篇文章带你玩转Hilt和依赖注入
放弃dagger?Anrdoi依赖注入框架koin
Koin 是为 Kotlin 开发者提供的一个实用型轻量级依赖注入框架,采用纯 Kotlin 语言编写而成,仅使用功能解析,无代理、无代码生成、无反射。
六月的雨
2020/07/28
1.7K0
放弃dagger?Anrdoi依赖注入框架koin
Hilt-依赖注入框架上手指南
Hilt 是Google 最新的依赖注入框架,其是基于Dagger研发,但它不同于Dagger。对于Android开发者来说,Hilt可以说专门为Android 打造,提供了一种将Dagger依赖项注入到Android应用程序的标准方法,而且创建了一组标准的组件和作用域,这些组件会自动集成到Android应用程序的各个生命周期中,以简化开发者的上手难度。
Petterp
2022/02/09
1.8K0
Hilt-依赖注入框架上手指南
Android 使用dagger2进行依赖注入(基础篇)
0. 前言 Dagger2是首个使用生成代码实现完整依赖注入的框架,极大减少了使用者的编码负担, 本文主要介绍如何使用dagger2进行依赖注入。如果你不还不了解依赖注入,请看这一篇。 1. 简单的依赖注入 首先我们构建一个简单Android应用。我们创建一个UserModel,然后将它显示到TextView中。这里的问题是,在创建UserModel的时候,我们使用了前文所说的hard init。一旦我们的UserModel的创建方式发生了改变(比如需要传入Context对象到构造函数),我们就需要修改所有
庞小明
2018/03/09
1.1K0
安卓软件开发:使用 Hilt 在 Jetpack Compose 和 M3 实现依赖注入App
Hilt 是 Android 官方推荐的依赖注入框架,简化了组件之间的依赖管理,特别是当项目复杂度增加时,依赖注入可以简化了代码。
Nimyears
2024/09/29
6220
[译] 格子拼贴 — 关于模块化的故事
在这篇文章中,我将全面介绍如何将一个整体的、庞大的、普通的应用转化为一个模块化应用束。以下是我们已取得的成果:
Android 开发者
2019/03/15
8190
[译] 格子拼贴 — 关于模块化的故事
Kotlin 中使用 Hilt 的开发实践
Hilt 是基于 Dagger 开发的全新的依赖项注入代码库,它简化了 Android 应用中 Dagger 的调用方式。本文通过简短的代码片段为您展示其核心功能以帮助开发者们快速入门 Hilt。
Android 开发者
2022/03/09
1.2K0
Hilt 稳定版发布 | 更便捷的 Android 依赖项注入
Hilt 是 Jetpack 推荐使用的 Android 应用 依赖项注入 (DI) 解决方案,现已 稳定。这意味着 Hilt 已经完全可以在 生产环境 中使用。Hilt 相比 Dagger 更加便捷,同时也能帮您减少模板代码,它专为 Android 而生,并集成了多个 Jetpack 依赖库。很多公司已在他们的应用中使用了 Hilt 并从中获益。
Android 开发者
2022/03/09
1.9K0
Hilt三问—你了解依赖注入吗
今天继续Jetpack专题,相信不少的朋友都使用过Dagger,也放弃过Dagger,因为实在太难用了。所以官方也是为了让我们更好使用依赖注入框架,为我们封装了一个新的框架——Hilt,今天一起来看看:
码上积木
2020/11/09
1.2K0
kotlin构建MVVM应用之依赖注入--Koin
这句为我们自动注入get()自动获得了UserRepository,然后实例化注入进来
大话swift
2020/04/16
1.9K0
kotlin构建MVVM应用之依赖注入--Koin
推荐阅读
相关推荐
带你了解Android Jetpack库中的依赖注入框架:Hilt
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验