【Android -- 新技术】模块化实践

一、前言

万维网发明人 Tim Berners-Lee 谈到设计原理时说过:“简单性和模块化是软件工程的基石;分布式和容错性是互联网的生命。” 由此可见模块化之于软件工程领域的重要性。

从 2016 年开始,模块化在 Android 社区越来越多的被提及。随着移动平台的不断发展,移动平台上的软件慢慢走向复杂化,体积也变得臃肿庞大;为了降低大型软件复杂性和耦合度,同时也为了适应模块重用、多团队并行开发测试等等需求,模块化在 Android 平台上变得势在必行。阿里 Android 团队在年初开源了他们的容器化框架 Atlas就很大程度说明了当前 Android 平台开发大型商业项目所面临的问题。

二、什么是模块化

《 Java 应用架构设计:模块化模式与 OSGi 》一书中对它的定义是:模块化是一种处理复杂系统分解为更好的可管理模块的方式。

上面这种描述太过生涩难懂,不够直观。下面这种类比的方式则可能加容易理解。

我们可以把软件看做是一辆汽车,开发一款软件的过程就是生产一辆汽车的过程。一辆汽车由车架、发动机、变数箱、车轮等一系列模块组成;同样,一款大型商业软件也是由各个不同的模块组成的。

汽车的这些模块是由不同的工厂生产的,一辆 BMW 的发动机可能是由位于德国的工厂生产的,它的自动变数箱可能是 Jatco(世界三大变速箱厂商之一)位于日本的工厂生产的,车轮可能是中国的工厂生产的,最后交给华晨宝马的工厂统一组装成一辆完整的汽车。这就类似于我们在软件工程领域里说的多团队并行开发,最后将各个团队开发的模块统一打包成我们可使用的 App 。

三、为什么需要模块化

在早期的 Java 开发中,提倡将整个项目结构按照程序的逻辑结构进行分层,比如表示数据的 Dao 层,表示控制器的 Control 层,表示 View 的 View 层,但是随着业务的不断迭代,发现这种分层方式有很大的弊端,代码难以定位,且后期难以维护。随后就出现了以业务结构划分的模式,这种结构彻底解决了以上问题。所以当前的APP基本上使用的都是这种以业务划分的模式,但随着 App 的不断迭代,业务变得越来越复杂,代码量越来越多,维护也变得越来越困难。还有一个明显的问题,Gradle 在编译的时候花费的时间越来越长,这大大降低了 APP 的开发效率。既然单个APP难以解决这个问题,那可以将项目进行拆分,每个人只需要负责开发、维护自己的模块即可。如何拆分呢?使用模块化技术按业务逻辑将 APP 进行划分,使得这些被拆分出来的模块可单独运行,这样就提高了编译速度,降低了维护成本。

优点:

  • 解耦,重用;
  • 降低维护成本,提高开发效率;

四、模块化的项目结构

在这里插入图片描述
从结构上来看,APP被划分成5层,每层的功能具体如下:

  • APP壳工程
    这是一个空的项目,其中只包含了一个 Application 的子类和一个 IntentService 的子类,主要用来对APP中使用的各种组件进行初始化,IntentService 的作用是为了提高 APP 冷启动的速度,将各种组件的初始化放在后台线程异步执行,这里需要注意的是,对于在 Applicaiton 或 SplashActivity 中就会使用的组件,最好直接在 Application 中进行初始化,否则会抛出未初始化的异常。

  • 业务层
    这里的业务层被划分为Main模块和其他模块(至于划分几个模块,根据自己APP的业务,选择合适的粒度进行划分即可)。这里的Main模块主要包括:新用户引导页,启动页,主页。具体业务方面的页面,都放在具体的业务模块中。

  • 公共组件层
    公共组件层主要包括APP中使用的第三方组件,这些组件基本都是现在APP的通用功能,为上层的业务层提供支持。至于模块划分,虽然这些都是单独的组件,但是每个做为一个Module未免有些繁琐了,所以还是推荐放在一个Module中。在选择第三方的库时,需要做一定的调研,尽量选择大公司,使用用户多的SDK,同时在使用时最好封装一下,这样后面更换时也方便。

  • 基础业务层
    基础业务层主要用来统一APP的代码结构,UI风格等,主要包含以下三个方面:

    • Android组件的二次封装
      主要是对Activity/Fragment的封装,提供了不需网络请求的BaseActivity/BaseFragment和需要网络请求的BaseProgressActivity/BaseProgressFragment, 为页面的代码提供统一的结构,页面的样式提供统一的风格。

    • 业务通用UI
      主要包含各种样式的Dialog, 自定义View等,根据APP的设计风格提供统一的样式;

    • 图片操作库
      图片操作库ImageSet是对图片组件库(包括Fresco, Glide, Universer ImageLoader)的封装,同时提供了调用系统相机/相册选择&裁剪照片,类似微信选择图片的组件,图片上传,图片压缩等功能。这个小模块其实也可放在Common组件层,只是觉得这里面也有一些业务相关的功能,所以就放在了这一层。
      当然,基础业务层还还包括APP设计风格中需要用到的各种动画,样式,颜色值,尺寸值等资源。在进行业务开发时,统一使用这些资源,为后续修改整个APP风格提供可能。

  • Common 组件层
    这里包含了一些通用的组件,包括各种常用的工具类,通用的UI库,数据源的封装(包括网络,文件,数据库)。这是一个APP的基本架构,里面包含的类基本不需要改动。所以在对工具类和通用UI进行定义时,需要考虑放置的位置是否准确。

五、实践

1. 项目结构

在这里插入图片描述
其中,MainModule, BaseComponentDemo, BaseLibraryDemoCommonBusinessDemo都是业务层模块,他们的关系如图所示:
在这里插入图片描述

MainModule 是整个 APP 的主模块,用来实现 APP 中主页和路由跳转相关的逻辑,同时也作为Application 与其他模块关联的枢纽。
BaseComponentDemo, BaseLibraryDemo和CommonBusinessDemo 是子业务模块,都依赖于library目录中的三个公共模块。这三个模块一方面是用来展示业务模块化实现过程,另一方面也是 library 中三个模块的示例代码。

项目地址:SimpleProject

2. 参考文献


版权声明:本文为duoduo_11011原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。