当前位置:首页 期刊杂志

基于Android软件开发组件化研究

时间:2024-05-04

殷 涛 崔佳冬

(杭州电子科技大学新型电子器件与应用研究所 浙江 杭州 310018)

0 引 言

Android历经十年,深受广大用户和研发人员青睐[1]。Android版本在6.0之前,主流软件开发有Eclipse和Android Studio(AS),其中Eclipse由ADT(Android Development Tools)插件结合SDK(software development kit)完成对Android开发环境的提供[2]。Eclipse中所有工程都并列在工程栏中,工程与工程之间的隔离并非太严格,各工程间除了映射资源无法直接引用外,其余的模块则可以通过添加库(lib)的形式依赖到主体工程使用。但Android版本6.0以后,由于官方不再提供ADT的更新,高版本Android的软件开发不得不向Eclipse过渡到AS。Studio集成开发环境(Integrated Development Environment,IDE)提供比Eclipse插件式开发更多的功能、更快的速度和高效的体验,但是AS中工程间隔离十分严格,工程间的依赖只有向主体工程中添加或新建模块的方式[3]。附加模块无法直接提供视图等自我调试的方式,只有通过主体工程一起工作,若改动一处,所有工程都需要重新编译一遍,这严重降低开发效率。同时,单一的功能模块跟随用户需求的增长逐渐变为一个庞大的功能族群。应用业务量的增多必然导致软件开发代码量的增大,Android应用(APP)开始出现代码臃肿,耦合度高等软件开发障碍,这严重违反移动应用的开发规范。因此,接入组件化开发,是未来Android大型工程开发的趋势[4]。

本文提出通过组件化思想,充分利用AS提供的Modules功能和Gradle插件,降低Android软件开发的耦合性、提高软件编译速度和应用协同开发效率。讨论组件化设计,并基于组件化思想开发了组件化测试模板APP。

1 组件化原理

Android软件开发组件化设计主要使用的IDE是AS。随着Android版本的升高,Eclipse结合ADT与SDK开发Android的应用变得越来越少,而AS集成开发环境提供最新Android版本的软件开发环境,同时,IDE提供Gradle插件负责项目的编译过程,组件化的实现就是由AS集成的Modules功能与编译插件Gradle完成。

AS工程中,除了默认创建的启动项目,即可以安装到手机系统的独立工程外,还可新建或添加依赖模块作为独立工程的依赖文件,默认情况下,依赖文件是一个lib库,只是为主工程提供功能服务和数据服务[5]。而IDE提供的Gradle插件是AS默认的构建工具,负责Android工程的依赖、编译、打包等过程,组件化设计使用Gradle插件在通用构建规则下,通过Groovy语言为Gradle指定新的构建规则,动态改变项目的编译过程[6]。在开发阶段,通过修改组件Gradle的Task、配置、编译类型和依赖等将模块改变为独立项目工程开发调试,可以在组件中添加启动视图、资源,打包APK下载安装。在调试阶段,改变Gradle文件配置,将模块作为项目依赖添加到主体工程中。组件化结构如图1所示,将一个整体的项目进行合理拆分,变为一个个小的组件,各组件间低耦合、高内聚,组件单独编译、同步开发,调试完毕后,组合各组件项目为一个大的工程,得到完整应用。

图1 组件化结构图

2 组件划分

软件开发中,组件的划分对于Android组件化设计尤为重要。移动应用开发通常需要经历一个漫长的过程,如项目立项、需求征集、应用开发、线下测试、线上发布等[7]。开发初期,项目的规模并不会很大,但随着需求的增多与版本的升级,项目变得越来越大,便可以将项目从不同的角度划分为多个组件,分别开发,根据每个开发团队的开发风格,Android工程可从以下三个方向划分组件。

(1) 从功能上划分。对于同一个业务类型的移动应用,如常见的电商型APP,工具型APP,在功能上都可以将应用划分为多个组件,常见的划分方式是将用户模块、业务模块与通信模块单独分离出来,如图2所示。

图2 APP功能组件划分

用户模块独立负责用户的登录、注册,用户信息管理等操作。业务模块负责具体的类型业务,如电商APP通过网络通信向后台服务端请求商品数据并在界面展示,工具型APP负责具体的业务场景等。通信模块主要包括模块内各个界面视图的通信,模块与模块之间的通信、APP与其他平台的通信等。若各组件之间不存在数据交互,如用户模块与业务模块,用户注册、登录后跳转业务界面,用户模块便已经销毁,如果业务模块需要用户信息,完全可以通过通信模块从后台或者其他通道直接获取,则组件与组件之间只需经过路由寻址即可。若存在数据交互则可以通过模块依赖或策略模式建立组件之间的相互通信。

(2) 从业务上划分。如社交类APP中的聊天业务、朋友圈业务、生活小工具等,在同一个APP下,两者业务上并不存在任何交集,分属不同的业务。通常大型APP开发除了集成必要的功能外,一些额外的附加功能也会根据用户需求隐藏在界面的某个触发按钮下,根据单点登录系统(CAS),每个组件都能获取到用户的信息[8]。一旦开发完成,除了主体业务常更新升级外,附加业务会存在长时间不变化的状态。从业务上划分组件,可以有效地进行Android软件工程的协同开发。

(3) 从架构上划分。Android软件开发常用的架构有MVC、MVP、MVVM等[9],根据软件的功能表现,将软件功能分为视图层、业务层以及连接层,如图3所示。

图3 移动应用架构层

视图层负责界面的展示和用户交互,业务层有本地业务和远程业务等,连接层负责视图层和业务层的通信[10]。各层之间通信比较紧密,因此在做组件化划分时,通常使用策略模式即接口实现各组价之间的通信[11]。开发过程中,利用顶层架构,可直接将软件从架构分为三层或以上,从架构划分组件,是在原有架构开发的基础上,更好地做到项目的解耦。

3 组件化设计

按照组件划分结果,完成软件开发组件化设计。使用AS新建Android开发工程,在工程的基础上建立名为moduleone、moduletwo、modulethree作为整体工程的三个组件。为进行组件式开发,具体步骤如下:

(1) 将主体工程修改为一个空壳工程,删除默认的MainActivity活动窗口和与之关联的所有路径,工程包下新建一个类继承Application负责主体应用生命周期的管理,其余内容全由其余组件填充。

(2) 在工程下创建config.gradle全局配置文件,并在工程下的build.gradle中使用apply from: config.gradle关联使用。在config.gradle中使用四个全局变量,控制主体应用和各组件模块的加载:

isModule=true

isModuleOne=true

isModuleTwo=true

isModuleThree=true

在Android编译时,各组件build.gradle文件中的apply plugin: ‘com.android.library‘或apply plugin: ‘com.android.application’将决定组件是依赖文件还是独立工程。因此,组件开发时根据config.gradle中的全局变量设置组件的工作方式:

if (rootProject.ext.isModuleOne) {

apply plugin: ’com.android.library’

} else {

apply plugin: ’com.android.application’

}

同时,通过相同的方法在Gradle依赖中建立主体工程与组件之间建立依赖:

if (rootProject.ext.isModule) {

implementation project(’:moduleone’)

implementation project(’:moduletwo’)

implementation project(’:modulethree’)

}

(3) 在各个组件中的build.gradle文件中添加动态资源配置:

sourceSets {

main {

if (rootProject.ext.isModuleOne) {

manifest.srcFile

’src/main/AndroidManifest.xml’

java {

exclude ’*module’

}

} else {

manifest.srcFile ’src/main/module/AndroidManifest.xml’

}}}

由于组件开发中各组件即可单独开发也可混合开发,因此需要使用两套不同的manifest配置文件分别适配不同的环境,即组件独立开发时使用新建的manifest文件,而依赖开发时使用默认的配置文件。两个文件的主要区别在于:独立开发时,manifest配置文件中有模块独立的Application的配置,而作为组件的模块中默认使用主体工程的Application作为应用的生命周期监控。

(4) 在每个组件的build.gradle文件中添加 resourcePrefix″xxx_″,为每个组件的资源强制添加前缀以保证资源不会出现名字重复的现象,防止各个组件之间资源名字的混淆。

(5) 使用阿里的ARouter框架采用编译时生成代码(APT)技术建立组件之间的路由,简化组件间的通信。在模块的build.gradle文件中使用远程依赖方式,获取ARouter的依赖,代码如下:

api ‘com.alibaba:arouter-api:x.x.x’

api ‘com.alibaba:arouter-annotation:x.x.x’

annotationProcessor ‘com.alibaba:arouter-compiler:x.x.x’

并为活动窗口界面使用以下代码添加路由:

@Route(path=”xxx”)

工程中,ARouter在使用前必须初始化,在全局Application中初始化ARouter,使用时直接获取该类的实例并调用方法,传入路由即可。ARouter初始化方法和路由跳转代码如下:

if (isDebug){

ARouter.openDebug();

ARouter.openLog();

}

ARouter.init(application);

//路由跳转

ARouter.getInstance().build(“xxx”).navigation();

4 应用程序实例

利用组件化思想完成测试工程的基本搭建,工程包括一个空壳的app模块、三个测试模块组件modulexxx和一个公共开发库component_base。工程项目结构如图4所示。

图4 项目结构图

程序默认加载moduleone作为工程的启动界面,分别对app、modulexxx进行开发测试,修改config.gradle中的全局配置变量。

(1) 测试组件单独编译安装,修改全局变量为:

isModule=false

isModuleOne=false

isModuleTwo=true

isModuleThree=true

即单独编译moduleone,点击编译工程,出现:

ARouter::Compiler >>> No module name

ARouter在组件路由中,编译时代码生成需要组件模块的模块名,在各个组件模块的build.gradle文件中添加如下代码后再编译:

javaCompileOptions {

annotationProcessorOptions {

arguments=[moduleName: project.getName()]

}}

如图5所示,APK打包状态已由工程打包变为了组件打包。

图5 工程打包与模块打包状态图

(2) 按照相同的方法,修改Gradle全局变量,对组件moduletwo、modulethree编译安装。

(3) 对组件整体测试,即打包所有组件为同一个APP,修改Gradle全局变量,编译安装,得到最终由组件开发的综合而成的应用,如图6所示。图中第一个APP为整体工程编译打包而成,由三个组件构成,其余三个APP是组件模块单独编译安装生成的APK。

图6 工程与组件APK

(4) 使用ARouter简单测试组件间路由功能。为每个组件的启动窗口添加如下代码,规定组件的路由:

@Route(path=ARouterUrls.PATH_XX)

其中ARouterUrls.PATH_XX为定义的路径全局常量字符串。工程默认加载组件moduleone,因此在moduleone中的启动界面中添加三个按钮,并对按钮设置监听,触发按钮测试组件路由跳转。由于Android的API14后,组件开发中的资源不再是常量[12],因此,对于多个控件的监听,不能使用switch-case结构。控件触发路由跳转部分代码如下:

@Override

public void onClick(View v){

int id=v.getId();

if (id==R.id.bt_module_two){

ARouterUtils.navigate(ARouterUrls.PATH_MODULE_TWO);

}else if (id==R.id.bt_module_three){

Bundle bundle=new Bundle();

bundle.putString(″data″,″moduleTwo2moduleThree″); ARouterUtils.navigate(ARouterUrls.PATH_MODULE_THREE, bundle);

}else if (id==R.id.bt_module_four){

ARouterUtils.navigate(ARouterUrls.PATH_MODULE_FOUR);

}}

其中ARouterUtils是对ARouter路由跳转代码的封装,内部代码为:

public static void navigate(String path){

if (TextUtils.isEmpty(path)){

return;

}

ARouter.getInstance()

.build(path)

.navigation();

}

测试路由经过moduleone跳转到moduletwo(如图7(b)所示),moduleone跳转到modulethree(如图7(c)所示)。图7(d)为测试未知路由跳转,由于开启了ARouter的调试模式和日志打印功能,未知路由跳转会触发异常捕获。

图7 路由跳转结果图

5 结 语

基于组件化思想的Android软件开发,是未来大型移动应用开发的趋势。将Android工程划分为多个组件,每个组件独立开发,独立编译,调试成功后通过Gradle插件集成到主体工程,极大降低了程序的耦合性,提高了开发的效率。同时,由于工程划分为组件,各组件单独编译,提高了IDE的编译效率。组件之间通过ARouter的路由功能简化通信,也方便了资源的复用。因此,通过组件化思想开发Android应用,可以完全应用于商业大型移动应用的开发。通过该思想开发了Android组件化测试工程,工程测试表明了方案的有效性和实际应用性。

免责声明

我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自各大过期杂志,内容仅供学习参考,不准确地方联系删除处理!