Android组件化/模块化开发(一)

上一篇文章发布之后又摸了小半年的鱼,前段时间精神状态确实很懒,写的东西都带有记流水账的性质。所以这次决定写点干货。
换了新工作之后,到新公司接手了公司以前的老项目。整个项目都是用coordova、ionic混合开发完成的。啃了两周的项目代码之后,觉得之前留下的摊子确实不好收拾,和产品确认过眼神之后,果断决定重启炉灶。
具体过程就不多啰嗦了,虽然说的是混合开发,不过总体来说仍然是原生为主,部分页面通过webview嵌入H5页面的方式来做展示,并不是网上所谓的一站式混合开发。不过个人认为这种方式才是更符合当前需求的一种方式,至于所谓的ionic之类的,demo很美好,需求很残酷。因为混合开发的缘故,从项目管理的角度和后期的维护性考虑,需要把H5相关的插件代码和原生代码分开,所以这里用到了模块化开发的方式。虽然这个项目目前只有我一个人,不过也正好可以试验一下自己以前想用而被上面无情pass掉的各种新技术。所以这篇文章主要介绍的是自己摸索并结合网上资料总结的一种组件化/模块化开发方式。对于这两种称谓,我个人没有太去纠结区别,所以下文可能会出现混用。本文的目的在于分享一种思路,大家就不要在意这些细节了。

  • 需求场景

    公司的老项目重构任务是要求把以前的ionic混合开发项目进行拆分,将大部分功能和主入口实现原生化,而商城这种业务变化较快的模块仍然保持H5方式展示。在第一版本的时候因为时间关系,只做了基础模块和主入口的原生化,剩下的大部分模块仍然是用老的coordova项目的代码打了一个aar包进来加载。也是在这个时候,因为项目中嵌入了大量配合coordova的代码,而这部分代码下个版本是注定要扔掉的,作为一个有强迫症的人,自然是不能容忍主项目里面有这些代码的,所以模块化的坑就这么挖起来了。

  • 模块化开发的优势

    一是结构清晰,各个模块的代码实现分离,不会搅在一起。在代码review或者二次开发的时候一目了然,不会满世界去找代码。
    二是协同开发的时候更灵活,不用再等同组其他同事的模块开发完成后才能运行app,自己负责的模块稍加修改就可以当做主app直接跑起来。
    三是便于维护。每个模块的代码、布局文件、资源文件可以随时从项目中通过gradle配置去除掉。

  • 基本思路

    公司接收的项目是一个货运平台app。按照功能划分,有货运模块、交易模块、货源模块、商城模块和个人中心。其中后两个是原项目的H5模块中的老代码,前三个是全部实现了原生化。所以基本结构就是原生入口,下分五个原生子页面。后两个原生子页面加载webview进行H5页面展示。
    这里先附上一张基本的项目结构图。


    一个基本的项目结构

    下面来说说这个项目的结构是怎么一步步整个成这样的。

    1.基本结构

    app模块是每个项目初始都有的,实质上仍然是一个module。Android Stuido项目中,我们和代码打交道的大部分时间都在module中。当然,具体的module机制我们不去深究,有时间可以另开一坑去研究。下面的三个module大家可以理解为java中的library,当然这样说不准确。
    app作为主要的module,主要承担了应用启动以及最上层的通用逻辑。比如在这个例子中,应用启动、首页展示和模块切换的业务逻辑都在这个模块。
    而下属的三个子模块承担了各自细分的业务,并且可以被app模块或者其他模块引用,每个模块只负责和考虑自己的业务。以此达到业务逻辑和代码分离的逻辑。

    按照之前的业务逻辑划分,项目结构可以先大致分为如下的结构:
    其中的箭头方向表示了引用关系
    2.系统层分离

    当然,仅仅这样是不够的。因为这样有一个问题,在AS中,module的引用是单向的。如果A module引用了B module,那么对A来讲,B是可见的,B的所有公开功方法理论上都可以在A中使用,但是对B来说,A是不可见的。所以,相面这样的结构出现的问题就是我们有大量的底层通用方法都放在app模块中,对于子模块来讲是不可见的,子模块无法引用封装好的底层方法,例如网络请求,图片加载,文件拷贝等,这肯定是不行的。所以这个结构还得再优化。

    按照module单向引用的原则,我们可以把公共底层通用方法单独分出来作为一个moduleBase,同时这个moduleBase也是最底层的module,保证对于其他module来说它都是可见的。这样还有一个好处就是这个moduleBase中的方法和配置大部分都是可以高度复用的。在新开其他项目的时候这个模块可以直接迁移到新项目中,而不用在为代码分离和剔除浪费时间。所以,项目的结构进一步细化成了如下的结构:

到这里,一个基本的结构就算完成了,但是这个结构仍然不完善。

3.公共层分离

上述的模块如果在使用中,有很大概率会遇到一个问题,部分的实体类、自定义view、布局文件或者资源文件在各个模块都需要用到,但是这些如果放在系统层的moduleBase里面,又会破坏系统层的通用性。所以,我们还需要一个公共层moduleCommon来专门提供上层业务逻辑模块的公共资源。直接上图:
4.细化与扩展

其实在第三步之后整个项目结构已经算是比较完整了,不过随着项目的不断扩大,模块仍然还是需要不断细分。这里说一下整个项目结构的一种规划思路。
在上述的项目结构中,严格来说只有三层:系统层、业务逻辑和app层。
其中app层是相对简单的,只要包含应用启动和初始化的一些额外操作和逻辑。而业务层包含了所有划分出来的子功能模块,为了方便项目结构的显示方便,我们可以把这些模块放在统一的文件夹下

同一层的module可以放在用一个文件夹下
这里需要注意的是放在文件夹下的module在引用时要注意带上相对路径。比如这里的moduleUser在引用时就要从":moduleUser"变成":moduleCore:moduleUser",多级以次类推。
同样,对中间层我们也可以采用类似的方式,因为中间层不仅会包含一些我们自定义的通用实体类等文件,还有可能会有我们常用的二次封装过的三方库和开源库。这些库有些本身就是一个module需要我们引入,有些则是我们经过二次封装的module。这些module同样不适合放在系统层,所以也可以归到公共层里,例如在我的项目里就有支付宝SDK,高德地图等通用moudle
最后在说一下系统层,虽然说这一层叫系统层,但是各个module之间实际上并不一定是平级关系的。比如在我的项目中我引入了greenDAO数据库框架。这个我作为一个单独的数据库模块放在了系统层,但是在层级上是最底层,被moduleBase引用。
最后,附上完整的设计思路和项目结构:
整体结构设计
这里需要说明一下各个模块之间的引用关系。建议各个模块在引用的时候都采用implementation的方式全部引用。例如app模块需要在gradle配置文件中引入所有需要用到的模块,这样可以不用考虑api方式产生的子模块继承引入的问题。例如app模块引入了moduleBill模块,而moduleBill引入了muduleA模块,那么app还需不需要引入这个模块呢?使用implementation的方式虽然繁琐了一点,但是也最大程度的保证了项目结构的清晰。
实际项目结构

到这里,一个基本的组件化项目结构就搭建完成了。这一部分主要是介绍了模块划分的逻辑和依据,偏向思想。实际开发过程中,因为各个module之间的引用关系还有很多的坑,这一部分我会在下一篇文章详细说明。这里就不在赘述。
最后,这种组件化的结构只是自己在实际项目开发中自己结合网上的资料摸索出来的,并不一定是最好的或最合理的,如果各位有更好的方法或思路,欢迎大家留言交流。

Android组件化/模块化开发(二)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容

  • 《迈向基地》是阿西莫夫基地系列中的前传,讲述了哈里·谢顿建立第一基地,第二基地的过程。在银河帝国日渐没落,川陀日渐...
    苏佑仁阅读 652评论 0 0
  • 红红的、沉甸甸的果实, 夏娃受到了你的诱惑, 你也曾挑起特洛伊的战争, 帕里斯说:阿芙洛狄忒最美。 牛顿坐在树下思...
    释迦干屎橛阅读 423评论 1 2
  • 历史总是惊人的相似,时隔一个月,我再次来到北京,而此次没有了第一次的激动和亢奋,更多的是责任与使命。 此次北京行,...
    苛娃阅读 740评论 6 5
  • 2017年6月27日,我毕业了。没有想象中的依依不舍,抱头痛哭,我只是淡定的走上讲台,从老师手里接过毕业证书...
    绯恋阅读 200评论 0 0