- 在 AndroidStudio 开发 Android 项目时,使用 Gradle 来构建,Google 官方提供了对应的 Gradle 插件,方便构建过程
- Android 工程往往会根据业务或功能划分为多个 Module(模块) ,一个主 Module,依赖 android application 插件来,该插件提供构建和打包 Android 应用等任务。主 Module 中通常标识了 Application 的入口及首个被启动的 Activity 等。
apply plugin: 'com.android.application' 复制代码
- 其他 Module 大多依赖 android library 插件,在应用打包时,依赖了 android library 插件的 Module 会被一同打到 apk 中。
apply plugin: 'com.android.library' 复制代码
-
之所以划分多个 Module,主要是利用 Android 开发中的 module 这个概念,将一个"功能"或"业务"作为一个 module,每个功能的代码都在自己所属的 module 中添加,module 之间在没有显示的声明依赖关系时是不能相互访问的,这样能够相对的降低耦合,易于管理。
-
但这样的设计在各个功能相互比较独立的情况下是比较合理的,但在业务比较复杂,功能耦合严重的项目中将难以维护。其主要的缺点有:
-
Module 粒度不好掌控,划分不合理,组织很混乱
-
Module 间相互依赖,关系复杂,耦合严重,且不方便重构和迁移
-
代码调试不够灵活,修改少量代码也需要运行整个项目查看结果,浪费时间;
-
组件化设计
粒度划分与组织
-
业务 Module 划分太细,难以组织,依赖复杂;业务和基础库、公共库之间没有明显区分,组织混乱;
-
分层
- 基础层
- baselib: 基础库
- 职责:底层网络封装(network)、通用 工具 类、json解析、加密算法
- 依赖:Gson、Glide、okHttp、Retrofit
- framework
- 职责: MVP、Router
- 依赖:无
- baselib: 基础库
- 公共层 - common
- 职责: 业务相关工具类,业务相关常量、TitleBar、公共资源等
- 依赖:api ':baselib' ':framework'
- 业务层 - modules
- 职责: 根据业务场景划分的多个模块,包括主 module 和多个业务 module,为了便于称呼,把一个业务 module 称为一个"组件"
- 依赖: implementation ':common'
- 基础层
-
如此一来,整个工程的结构被分为三层,日常开发基本只需要关注最后一层即可。工程架构变成了一个主模块挂载多个业务模块,共同依赖几个功能模块的模式,将这种结构称之为**"组件化"**结构。层次结构及依赖关系图:
-
理想情况下,主模块承载的业务能力应该尽可能的少,可以只作为整个应用的"壳儿",除应用的初始化配置及主 activity 外,尽量不包含其他业务。
-
主模块决定挂载哪些业务组件,在应用的初始化过程中进行配置。
组件间解耦
-
组件间通信:接口
-
业务组件间依赖通过接口发生,实现类不发生直接依赖关系
-
把每个业务组件对外提供的接口统一存放,可以抽成一个单独模块,比如 service,其中 common 依赖 service
-
在应用启动时将所有组件的接口注册到接口管理器中,以便于在任何一个业务组件中,都可以访问到其他组件的接口,进而与之通信。当然,接口的实现类在对应的业务组件内。
-
-
组件间跳转:Router
- 使用现有 Router 机制,放在 framework 中
- Router 实现了从 String -> Class 的映射,也就实现了解耦
快速运行调试
- 目标:日常开发中,业务组件可以单独运行。这样,在针对某个组件修改需求时,可以只运行该组件就可以看到结果或者单步调试,提高编译速度,节省时间。应用打包时,业务组件依然一并输出到 app 中。
- 基本思想:既然业务组件即可以单独调试,又可以被主 Module 依赖,那么业务组件依赖的 Android 插件就需要动态配置。可以在 debug 模式下,每个组件不再依赖 'com.android.library',而是依赖 'com.android.application' 插件,release 模式下,组件依然依赖 'com.android.library' 插件。这样能够实现,在 debug 模式下,组件以 application 的形式存在,在 release 模式下,组件依然以 library 的方式打到同一个 apk 中。
- 实现方式:自定义 gradle 插件,根据项目的配置文件(如 当前是否为debug模式、哪个 module 是主module,哪些是组件),动态选择依赖模式 'com.android.library' 或 'com.android.application'
- 还要解决的问题
-
应用初始化配置
- 很多工具类都需要初始化才能使用,最常见的是传入 context,我们一般在 app 的 Application 的 onCreate 时对这些类进行初始化工作。
- 同理,当组件以 application 方式运行时,我们也可以指定入口 Application,来进行一些初始化工作,注意,该 Application 只有在 debug 模式下才起作用
- 可以通过 gradle 的 sourceSets 的配置,指定 debug 模式下 java 目录和 res 目录
-
指定 launcher activity
-
同样,通过 gradle 的 sourceSets 的配置,也可以指定 manifest 文件,就可以在 manifest 中配置 launcher activity
sourceSets { main { if (Boolean.valueOf(rootProject.getProperties().get("isDebug"))) { manifest.srcFile 'src/main/debug/AndroidManifest.xml' java.srcDirs = ['src/main/java', 'src/main/debug/java'] res.srcDirs = ['src/main/res', 'src/main/debug/res'] } } } 复制代码
-
-
其他需要解决的问题
- 组件与接口的注册
- 挂载哪些业务组件应该由主模块决定,这样甚至可以实现动态下发配置,来挂载不同的业务组件
- 接口的注册应该由每个组件自己决定,组件初始化时,决定要对外提供哪些接口
- 业务组件和接口的注册应该尽可能早,以便于其他组件的访问。无疑在应用启动初期就要进行注册以及必要的初始化工作,可以选择在主业务的 application 的 onCreate 生命周期注册组件。而且主模块不能与其他业务组价产生依赖,一种比较好的方式是通过反射解耦。
- 另外,业务组件以 library 运行时,是没有 application 的,需要给它制造一个类似的初始化时机。可以定义类似具有 onCreate 方法的接口,在主模块中依赖该接口,并通过反射,对业务组件进行初始化工作。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 组件化之路—集成组件SDK
- Android组件化入门:一步步搭建组件化架构
- Android快速开发框架,基础库,样式库,组件化,组件集成
- Android组件化方案及组件消息总线modular-event实战
- 组件化实践
- 组件化架构漫谈
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
《裂变:秒懂人工智能的基础课》
王天一 / 电子工业出版社·博文视点 / 2018-6-13 / 59.00元
人工智能是指通过普通计算机程序实现的人类智能技术,这一学科不仅具有非凡的科学意义,对人类自身生存方式的影响也在不断加深。本书作为人工智能领域的入门读物,内容围绕人工智能的核心框架展开,具体包括数学基础知识、机器学习算法、人工神经网络原理、深度学习方法与实例、深度学习之外的人工智能和实践应用场景等模块。本书力图为人工智能初学者提供关于这一领域的全面认识,也为进一步的深入研究建立坚实的基础。一起来看看 《《裂变:秒懂人工智能的基础课》》 这本书的介绍吧!