Android应用开发之Android 项目架构 组件化基础介绍
凌雪 2018-10-24 来源 :网络 阅读 782 评论 0

摘要:本文将带你了解Android应用开发之Android 项目架构 组件化基础介绍,希望本文对大家学Android有所帮助。

本文将带你了解Android应用开发之Android 项目架构 组件化基础介绍,希望本文对大家学Android有所帮助。


Android   项目架构 组件化基础介绍
什么是模块化、组件化、插件化
模块化 Modular programming
Modular programming is a software design   technique that emphasizes separating the functionality of a program into   independent, interchangeable modules, such that each contains everything   necessary to execute only one aspect of the desired functionality.
模块化是一种软件设计理念,它强调将程序拆分成相互独立的、不可变的模块,其中每个模块只包含与其功能相关的模块。
组件化 Component-based software engineering
Component-based software engineering (CBSE),   also known as component-based development (CBD), is a branch of software   engineering that emphasizes the separation of concerns in respect of the   wide-ranging functionality available throughout a given software system. It   is a reuse-based approach to defining, implementing and composing loosely   coupled independent components into systems. This practice aims to bring   about an equally wide-ranging degree of benefits in both the short-term and   the long-term for the software itself and for organizations that sponsor such   software.
组件化强调了如何将一个大的系统拆分成各个的独立的组件。
它提供了一种可重用的方式来定义、实施和组合各个低耦合的松散的组件到一个系统中。
插件化
组件化和插件化的概念与用处一样,但最大区别(应该也是唯一区别)就是组件化在运行时不具备动态添加和修改组件的功能,但是插件化是可以的。
项目架构
了解基本概念,梳理现在基本上在使用的两种架构类型:
一种是现在使用的 单一工程,多个lib   的架构,这种架构很常见,其中多个lib也可能是由gradle引入; 另外一种是 主工程,多组件 的架构,即组件化。这也是我们在实践和即将要实践的架构。
1. 主工程,多library
依靠包名来区分业务,且分包会不明确,且复用性低; 业务包和业务包之间直接相互调用,强耦合;   需要编译整个项目,效率低; 写需求时沟通成本高;
   
    2. 主工程多组件(组件化)
   
    组件化在Android中的应用是在基于gradle的不同配置上进行的,特点是:一个组件可以作为一个module(project)被主组件compile运行,也可以单独作为一个application直接运行。
这点也可以成为Android上的组件化原理。
Android 项目架构 组件化基础介绍
什么是模块化、组件化、插件化
模块化 Modular programming
Modular programming is a software design   technique that emphasizes separating the functionality of a program into   independent, interchangeable modules, such that each contains everything   necessary to execute only one aspect of the desired functionality.
模块化是一种软件设计理念,它强调将程序拆分成相互独立的、不可变的模块,其中每个模块只包含与其功能相关的模块。
组件化 Component-based software engineering
Component-based software engineering (CBSE),   also known as component-based development (CBD), is a branch of software   engineering that emphasizes the separation of concerns in respect of the   wide-ranging functionality available throughout a given software system. It   is a reuse-based approach to defining, implementing and composing loosely   coupled independent components into systems. This practice aims to bring   about an equally wide-ranging degree of benefits in both the short-term and   the long-term for the software itself and for organizations that sponsor such   software.
组件化强调了如何将一个大的系统拆分成各个的独立的组件。
它提供了一种可重用的方式来定义、实施和组合各个低耦合的松散的组件到一个系统中。
插件化
组件化和插件化的概念与用处一样,但最大区别(应该也是唯一区别)就是组件化在运行时不具备动态添加和修改组件的功能,但是插件化是可以的。
项目架构
了解基本概念,梳理现在基本上在使用的两种架构类型:
一种是现在使用的 单一工程,多个lib   的架构,这种架构很常见,其中多个lib也可能是由gradle引入; 另外一种是 主工程,多组件 的架构,即组件化。这也是我们在实践和即将要实践的架构。
1. 主工程,多library
依靠包名来区分业务,且分包会不明确,且复用性低; 业务包和业务包之间直接相互调用,强耦合;   需要编译整个项目,效率低; 写需求时沟通成本高;
   
    2. 主工程多组件(组件化)
   
    组件化在Android中的应用是在基于gradle的不同配置上进行的,特点是:一个组件可以作为一个module(project)被主组件compile运行,也可以单独作为一个application直接运行。
这点也可以成为Android上的组件化原理。
即业务组件之间是独立的,没有关联的,这些业务组件在集成模式下是一个个library,被app壳工程所依赖,组成一个具有完整业务功能的APP应用;但是在组件开发模式下,业务组件又变成了一个个application,它们可以独立开发和调试。
组件化基于这样的特性的好处多多(插件化也应该如此):
各个组件间代码和资源相互隔离,不存在直接的相互调用,复用性强   各个组件可以单独修改,单独运行,单独编译,没有关联,开发效率高,测试成本低 新增、修改、删除业务组件简单便捷,完成需求、定位bug效率高   团队成员上手快,沟通成本降低
如何实施组件化
即在上面说的组件化的原理,主要是通过配置gradle脚本来完成组件化。
在gradle.properties中添加isRunAlone属性,用于控制组件是否单独运行。
主工程中,始终是作为application存在,其他的组件被其引用,组成一个整体的app。
组件中,根据isRunAlone决定是作为application单独运行,还是作为library来运行。
主工程中:
?12345678910111213141516171819202122apply   plugin: 'com.android.application' android{  sourceSets   {        main   {            java.srcDirs   = ['src/main/java']        }    }} dependencies   {    implementation project(':module_service')    //组件通信库    implementation project(':module_common:lib_common')   // 基础库     if (isRunAlone.toBoolean())   {    } else   {        implementation   project(':component_one')        implementation   project(':component_two')        implementation   project(':component_three')    } }
组件中:
?123456789101112131415161718192021222324252627282930//   单独运行时使用application,否则则作为Library使用if (isRunAlone.toBoolean())   {    apply plugin: 'com.android.application'} else   {    apply plugin: 'com.android.library'} android   {  sourceSets {        main   {            //   单独运行时指定额外所使用的java资源、res资源和manifest            if   (isRunAlone.toBoolean())   {                manifest.srcFile   'src/main/runalone/AndroidManifest.xml'                java.srcDirs   = ['src/main/java',   'src/main/runalone/java']                res.srcDirs   = ['src/main/res', 'src/main/runalone/res']            }   else   {                java.srcDirs   = ['src/main/java]            }        }    }    resourcePrefix   "gank_" //组件中资源命名规范} dependencies   {    implementation fileTree(dir: 'libs', include:   ['*.jar'])     //数据库    implementation   project(':module_common:lib_common')    implementation   project(':module_service')}
在这种思想的引导下,我们只需要关心如何做好隔离,如何更好地设计,以提高开发效率。
接下来主要就是 解决组件间如何通信以及如何传递数据。
组件间如何传递数据、UI跳转
这里采用得到的方案,即组件间在彼此无法互相访问的时候的接口定义和调用。
每个组件在module_service中声明自己提供的服务Service,module_service和module_common一样都是要被所有组件引用的,一个是通信的基础库,另一个是下沉的基础库。
这些组件在module_service中声明的Service都是一些抽象类或者接口,Service的实现类在自己的组件中,组件负责将这些Service实现并注册到一个统一的路由Router中去。
如果其他要使用某个组件的功能,只需要向Router请求这个Service的实现,具体的实现细节我们全然不关心,只要能返回我们需要的结果就可以了。
组件如何将这些Service的实现注册到Router中。
使用ApplicationDeletegate的概念,在其中添加了组件的生命周期方法。在具体实现类中的ApplicationDelegate#onCreate方法中,将自己实现的ServiceImpl注册到Router中。
这块就介绍这么点了,在实践中不断丰富这块的内容。具体的通信、包括传输Fragment、startActivityForResult、EventBus等,都得在具体的实践中去完善。
得到提供方案的优点
得到使用了gradle插件去解耦组件和组件之间的强依赖,而去依赖了配置,在编译期间进行组合;这样的思路很清晰,也很易懂。
而且组件可以依赖别的组件,一个app中可以有多个可以依赖别的组件的application。
这样极大的方便了组件之间之间的组合,也方便了测试。
感谢得到的开源,微信也提供了更好的在业务层面的组件分离的方式,即将Accout等公共信息直接封装在业务基础层,即用户这块作为基础层存在,避免了作为组件而频繁通信的情况。
   
    下面是自己项目进行组件化的笔记。
Daily重构
遇到的问题:
1. 如何拆分基础库,什么是基础库
包含网络、图片、数据库等的即为基础库,其中网络层面的基础设置也应该被包含到该层次,不要过度设计。
还有基于BaseApplication的Context获取;BaseView层面;CommonUtil层面等
主题theme、style的拆分
library中使用ButterKnife导致R2和R1 toolbar的id不一致
已删除butterknife,在组件化中不使用
app_name
gradle中添加   resourcePrefix进行隔离,在写基础库时也要注意app_name的冲突
传递Fragment,传递数据
将Fragment在Application在初始化时放入Map中,像router那样获取它,ApplicationDelegate
组件生命周期,在MainApplication初始化时初始各个组件,组件开始向中间件注册服务(跳转、获取View等)
UI跳转,即组件间的相互跳转
可否以服务的方式注册,而不是单独的router,如果不考虑更多的扩展的话。
自己配置gradle而不使用插件来动态配置问题:
无法做到其中一个组件是application去依赖其他组件,因为application只有一个,其他的要么是module要么是application。
且动态配置基本上完全隔离了组件在gradle中进行compile,这样删掉一个组件也不会报错。
即业务组件之间是独立的,没有关联的,这些业务组件在集成模式下是一个个library,被app壳工程所依赖,组成一个具有完整业务功能的APP应用;但是在组件开发模式下,业务组件又变成了一个个application,它们可以独立开发和调试。
 
组件化基于这样的特性的好处多多(插件化也应该如此):
各个组件间代码和资源相互隔离,不存在直接的相互调用,复用性强   各个组件可以单独修改,单独运行,单独编译,没有关联,开发效率高,测试成本低 新增、修改、删除业务组件简单便捷,完成需求、定位bug效率高   团队成员上手快,沟通成本降低
如何实施组件化
即在上面说的组件化的原理,主要是通过配置gradle脚本来完成组件化。
在gradle.properties中添加isRunAlone属性,用于控制组件是否单独运行。
主工程中,始终是作为application存在,其他的组件被其引用,组成一个整体的app。
组件中,根据isRunAlone决定是作为application单独运行,还是作为library来运行。
主工程中:
?12345678910111213141516171819202122<code><code><code><code><code><code>apply   plugin: 'com.android.application' android{  sourceSets   {        main {            java.srcDirs   =   ['src/main/java']        }    }} dependencies   {    implementation project(':module_service')    //组件通信库    implementation   project(':module_common:lib_common') // 基础库     if   (isRunAlone.toBoolean()) {    } else   {        implementation project(':component_one')        implementation   project(':component_two')        implementation   project(':component_three')    } }</code></code></code></code></code></code>
组件中:
?123456789101112131415161718192021222324252627282930<code><code><code><code><code><code>//   单独运行时使用application,否则则作为Library使用if (isRunAlone.toBoolean())   {    apply plugin: 'com.android.application'} else   {    apply plugin: 'com.android.library'} android   {  sourceSets {        main   {            //   单独运行时指定额外所使用的java资源、res资源和manifest            if   (isRunAlone.toBoolean())   {                manifest.srcFile   'src/main/runalone/AndroidManifest.xml'                java.srcDirs   = ['src/main/java',   'src/main/runalone/java']                res.srcDirs   = ['src/main/res',   'src/main/runalone/res']            }   else   {                java.srcDirs   =   ['src/main/java]            }        }    }    resourcePrefix   "gank_" //组件中资源命名规范} dependencies   {    implementation fileTree(dir: 'libs', include:   ['*.jar'])     //数据库    implementation   project(':module_common:lib_common')    implementation   project(':module_service')}</code></code></code></code></code></code>
在这种思想的引导下,我们只需要关心如何做好隔离,如何更好地设计,以提高开发效率。
接下来主要就是 解决组件间如何通信以及如何传递数据。
组件间如何传递数据、UI跳转
这里采用得到的方案,即组件间在彼此无法互相访问的时候的接口定义和调用。
每个组件在module_service中声明自己提供的服务Service,module_service和module_common一样都是要被所有组件引用的,一个是通信的基础库,另一个是下沉的基础库。
这些组件在module_service中声明的Service都是一些抽象类或者接口,Service的实现类在自己的组件中,组件负责将这些Service实现并注册到一个统一的路由Router中去。
如果其他要使用某个组件的功能,只需要向Router请求这个Service的实现,具体的实现细节我们全然不关心,只要能返回我们需要的结果就可以了。
组件如何将这些Service的实现注册到Router中。
使用ApplicationDeletegate的概念,在其中添加了组件的生命周期方法。在具体实现类中的ApplicationDelegate#onCreate方法中,将自己实现的ServiceImpl注册到Router中。
这块就介绍这么点了,在实践中不断丰富这块的内容。具体的通信、包括传输Fragment、startActivityForResult、EventBus等,都得在具体的实践中去完善。
得到提供方案的优点
得到使用了gradle插件去解耦组件和组件之间的强依赖,而去依赖了配置,在编译期间进行组合;这样的思路很清晰,也很易懂。
而且组件可以依赖别的组件,一个app中可以有多个可以依赖别的组件的application。
这样极大的方便了组件之间之间的组合,也方便了测试。
感谢得到的开源,微信也提供了更好的在业务层面的组件分离的方式,即将Accout等公共信息直接封装在业务基础层,即用户这块作为基础层存在,避免了作为组件而频繁通信的情况。
   
    下面是自己项目进行组件化的笔记。
Daily重构
遇到的问题:
1. 如何拆分基础库,什么是基础库
包含网络、图片、数据库等的即为基础库,其中网络层面的基础设置也应该被包含到该层次,不要过度设计。
还有基于BaseApplication的Context获取;BaseView层面;CommonUtil层面等
主题theme、style的拆分
library中使用ButterKnife导致R2和R1 toolbar的id不一致
已删除butterknife,在组件化中不使用
app_name
gradle中添加   resourcePrefix进行隔离,在写基础库时也要注意app_name的冲突
传递Fragment,传递数据
将Fragment在Application在初始化时放入Map中,像router那样获取它,ApplicationDelegate
组件生命周期,在MainApplication初始化时初始各个组件,组件开始向中间件注册服务(跳转、获取View等)
UI跳转,即组件间的相互跳转
可否以服务的方式注册,而不是单独的router,如果不考虑更多的扩展的话。
自己配置gradle而不使用插件来动态配置问题:
无法做到其中一个组件是application去依赖其他组件,因为application只有一个,其他的要么是module要么是application。
且动态配置基本上完全隔离了组件在gradle中进行compile,这样删掉一个组件也不会报错。    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

本文由 @凌雪 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程