在Android上编写模块化项目(翻译)
原文:https://medium.com/mindorks/writing-a-modular-project-on-android-304f3b09cb37
在Android上编写模块化项目(翻译)
当我们在 Android Studio 上创建一个新的项目时,自带一个 app
module。这时我们大多数人编写整个应用的地方。每次点击 run
按钮都会触发我们整个所有 module 上的 gradle 构建,并检查所有文件是否有变化。这就是为什么 gradle 构建会在更大的应用程序上花费 10分钟的时间,并且减慢开发者的输出。
要解决这个问题,复杂的应用程序,如 Uber 决定对它们的应用程序进行模块化并从中获得了很多。下面是试用模块化项目的一些优势:
- 更快的 gradle 构建
- 跨应用/模块复用通用的功能
- 易于插拔到Instant apps
- 更好的团队工作,一个人可以单独负责一个模块
- 更流畅地git flows
由于上述优势,当我刚开始Posts这个应用时,我就在始终坚持使用模块化方法。对此,Android 团队已经给我们提供了一些工具,但是我确实遇到了一些障碍,一下是我学习到的内容:
我该怎么分割我的 modules ?
你的应用程序是流程集构成的,比如,Google Play 有应用详情流,它包含了简要,描述详情,应用截图,评论活动等。
所有这些都可以归为同一模块 —— app-details
。
你的应用会包含多个类似流程的模块,有 authentication
, settings
, on-boarding
等等。当然还有一些不需要UI元素呈现的模块如 —— notifications
, analytics
, first-fetch
等等。这些模块包含与流程有关的 activities, repositories, entities和依赖注入相关东西。
但是这些模块中总是有一些共同的功能和工具。这就是为什么你需要一个 core 模块。
什么是 core 模块 ?
Core
模块是一个你项目中简单的 module 库。core 库可以(除其它外),
- 给你的依赖注入框架提供全局依赖,如 Retrofit, SharedPreferences等等。
- 包含工具类和扩展方法
- 包含全局类和回调
- 在 application 类中的初始化库,如 Firebase Analytics,Crashlytics,LeakCanary,Stetho等等
怎么使用第三方库?
核心(core
)模块的其中一个职责是为你的功能(feature
)模块提供外部依赖。这使得很容易实现在你的 feature
模块中共享相同版本的库。只需要在你的 core
模块的 dependencies 中使用 api
,这样你就能在所有 feature
模块中使用它们。
1 | dependencies { |
有种依赖的可能性是只有对 feature-a
模块有用,但是在 feature-b
中无用。对于这种情况,我推荐在你的 core 的依赖中使用 api
,因为 proguard 注意到而不会包含在 feature-b
instant app 中。
怎么使用 Room ?
这个困扰我挺久的时间。我们希望把我们的数据库定义到 core
模块中,因为它是我们应用程序要共享的通用的功能。为了让 Room 工作,你需要一个包含了所有 entity 类的数据库文件。
1 |
|
但是,如上面提到的,我们的 entity 类是被定义在 feature
模块中,而且 core
模块不能去访问它们。这是我碰到障碍的地方,经过一番思考后,你做了一件最棒的事,寻求 Yigit 的帮助。
Yigit 阐明了观点,你必须要在每个 feature
模块中都创建一个新的 db 文件,然后每个模块一个数据库。
这有几个好处:
- 迁移是模块化的
- 即时 app 仅包含它们需要的表
- 查询会更快
缺点:
- 跨模块数据关系将不可能
注意:为了 Room 的注解能够工作,不要忘记在你的 feature
模块中增加下面依赖
1 | kapt "android.arch.persistence.room:compiler:${versions.room}" |
怎么使用 Dagger 2 ?
同样的问题 Dagger 也遇到了。我的 core 模块中的 application 类不能访问和初始化我 feature
模块中的组件。这是从属组件完美的用例。
你的 core 组件定义了它想要暴露给依赖组件的依赖关系
1 |
|
您的模块组件将 CoreComponent
定义为依赖项,并使用传递的依赖
1 |
|
在哪里初始化我的 components ?
我为我的功能的所有组件创建了一个单例 holder。这个 holder 用于创建,维护和销毁我的 component 实例。
1 |
|
注意:为了 Dagger 的注解能够工作,不要忘记在你的 feature
模块中增加下面依赖
1 | kapt "com.google.dagger:dagger-compiler:${versions.dagger}" |
总结
尽管把你的单独的 application 转成模块化有一些棘手,其中一些我试图通过上面的方法来解决,优点是深刻的。如果您在模块中遇到任何障碍,请随时在下面提及它们,我们可以一起讨论解决方案。
谢谢。
本文链接:https://blog.wangjiegulu.com/2018/02/13/writing_a_modular_project_on_android/
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处。