阿里四面我败了!原因竟然是我信心满满掌握的“组件化架构”...
一、组件化架构的由来
随着移动互联网的不断发展,很多程序代码量和业务越来越多,现有架构已经不适合公司业务的发展速度了,很多都面临着重构的问题。在公司项目开发中,如果项目比较小,普通的单工程+MVC架构就可以满足大多数需求了。
但是像淘宝、蘑菇街、微信这样的大型项目,原有的单工程架构就不足以满足架构需求了。
就拿淘宝来说,淘宝在13年开启的“All in 无线”战略中,就将阿里系大多数业务都加入到手机淘宝中,使客户端出现了业务的爆发。在这种情况下,单工程架构则已经远远不能满足现有业务需求了。
所以在这种情况下,淘宝在13年开启了插件化架构的重构,后来在14年迎来了手机淘宝有史以来最大规模的重构,将其彻底重构为组件化架构。
二、初始模型
我以一个实际例子来一边讲解一边搭建项目结构,就以我们上面举的资讯类app例子,它包含三个业务模块:首页、视频、我。
那么我们的项目初始架构会是这样的:
相信看完这个图,你脑海里会马上浮现两个疑问:app外壳是什么?为什么又多了个main组件,这个家伙用来干什么的?
这里我们可以做一个比喻,把我们的app比喻成一个电脑主机,那么app外壳就是主机外壳,main组件就是主板,其他各个组件就类似于网卡、显卡之类的东西,各个组件连接到主板上,安装在主机壳中,对外展示为一个单一的电脑主机。
在我们的项目中,实际展示出来的效果应该是这样的:
或者我们可以用另外一种目录结构来看,可能更清晰
这里需要注意一下,main组件的gradle文件中,apply plugin使用的是com.android.application
其他业务模块,使用的是com.android.library
因为在最终的发布版中,其他业务组件是集成到main组件中的,main组件编译生成最终的application,或者可以这么理解;
main组件和app外壳是我们app的必备组成部分,一起构成了可对外发布的完整app,其他组件可以以集成进来,也可以不集成进来,只会增加或者减少我们app的功能,但不影响我们app的最终发布。所以我们在新增module的时候,选择的类型应该是library。
各个组件都建立完成之后,接下来可以把组件集成到main组件中,集成非常简单,只需在main组件的gradle文件中,添加如下语句
dependencies{ …… compile project(':home') compile project(':personal') compile project(':video')}
接下来做些有实际效果的事情,给各个组件写一个页面,再集成到我们的main组件中展示。
实现非常简单,就是在三大业务组件中,分别定义一个fragment,然后在main组件中,把这些fragment实例化加载到主页面就行。由于我们前面已经把三大业务组件都引入到了main组件中,所以编码和在同一个module中的编码是一样的,不需要做特别处理。
到此就实现了“组件化架构”了么?当然没那么简单,目前只是非常简单的集成。“组件化”不仅仅是把各个功能模块分开,还有模块之间如何通信,以及“组件化”的一大亮点------各个组件可以单独开发。
三、各组件单独开发
前面我们把各个组件集成到到main组件,现在我们把组件拆出来,单独开发,开发完后,可以再把组件集成到main中,发布。这是组件化开发的最大亮点(优点)。
这里我们把home组件单独出来开发。第一步,需要把其library模式改为application模式,因为只有application才可以单独运行,library必须依靠application才能运行。所以,接下来,我们就要在home所对应的gradle文件中做修改。
修改成
等要集成到main组件时,又得改回来,如果这样子手工去改,组件一多,修改起来麻烦,也不优雅。优雅的解决办法就是,设置一个开关,打开时,就是application模式,可以单独开发,关闭时,就是library模式,可以集成到main组件中。
在项目根目录下,有一个gradle.properties文件
在这文件中,我们可以添加一个常量isDebug,值设为true。
这里设置了常量之后,我们项目中的其他build.gradle文件都可以把这个常量读取出来,所以我们可以在home的build.gradle文件中,读取该常量的值,动态设置applyplugin。
这样子设置之后,当我们需要切换模式时,只需要修改gradle.properties文件中isDebug的值,修改完成之后,点击Project sync按钮同步一下,如果有报错,那么还有个地方需要修改一下,就是main组件的build.gradle文件,看下图
为什么做这样的修改?因为我们把module的模式改成了application了,这里不能引入application,引入的话会报错,所以当是debug模式时(也就是组件单独开发时),这里就不引入该组件,免得报错。
接下来,还得修改 AndroidManifest.xml。因为当我们把一个module设置为application时,其AndroidManifest.xml需要包含一个app所需要的属性,例如app的icon、theme、launch Activity这些属性设置,而当module为library时,上面所提的这些属性都不需要用到,所以当我们处于不同模式时,AndroidManifest.xml文件也得不同。
我们在home的src文件夹中新创建一个目录为debug目录,再把我们用于debug时的AndroidManifest.xml文件放进去。由于在Android目录模式下比较难创建这个目录,所以我们可以选另外一种目录模式(Project目录模式),然后再创建debug目录(很绕,直接看下图就会明白了)。
AndroidManifest.xml文件内容可以这样写
以上内容会有很多错误提示,其实提示的无非就是资源找不到,我们只需要把这些资源给加上就好了。可以把main组件中相应的资源拷贝过来,放在对应的目录下就可以了。
接下来在home组件的build.gradle文件中,指定不同模式下的AndroidManifest.xml文件。
以上设置完成,并且sync project之后,home组件会是这样的目录
并且android studio的运行app里面,多了一个可运行的app,就是home。
由于我们home组件集成到main组件中时,是以一个fragment界面集成上去的,所以我们的home组件中,没有一个MainActivity可以作为LaunchActivity,我们可以创建一个,然后把fragment在MainActivity的layout xml文件中放进去就可以了。
所对应的activity_main.xml**布局文件如下
以上步骤完成之后,home就可以单独作为一个app来开发了,我们可以直接运行该组件。
效果图
再来尝试一下把home组件集成到main组件中,我们只需把isDebug的值修改为false,然后syncproject,此时可以看到我们的home作为app时被打了个叉叉,表示不能用了。
选择一下main组件,运行。
运行成功,又集成到我们的完整项目里面了。
四、“组件化”的优点
至此,我们已经可以随意的集成或者拆分组件,这里总结一下“组件化”的优点:
1、业务模块分开,解耦的同时也降低了项目的复杂度。
2、开发调试时不需要对整个项目进行编译。
3、多人合作时可以只关注自己的业务模块,把某一业务当成单一项目来开发。
4、可以灵活的对业务模块进行组装和拆分。
总而言之,言而总之,就是把一个项目分开成多个项目所具有的优点。
五、总结
项目发展到一定阶段时,随着需求的增加以及频繁地变更,项目会越来越大,代码变得越来越臃肿,耦合会越来越多,而开发人员掌握组件化这门技术就显得“尤为重要”,甚至有一部分原因能决定开发人员的薪资涨幅;
为了能够帮助大家能快速理解组件化架构,能形成自己的组件化架构技术知识体系,以便以后无论是在工作中还是面试中遇到难题可以提供相应的办法和解决方案。
我把腾讯T4的组件化架构复习笔记已整理成PDF,需要的朋友————(此处免费打包领取)
另外快到金九银十跳槽季了,为了帮助朋友在金九银十跳槽涨薪。备用2020年互联网一二线企业1593道Android高阶面试题(含答案解析),包含互联网71个一二线公司Android岗面试真题,已分类已整理好。
六、后话
由于本项目并没有太多业务逻辑,实际情况中要比这更复杂,如果大家有什么问题,欢迎留言讨论,一起解决。
需要①组件化架构复习笔记完整版PDF+②备用2020年互联网一二线企业1593道Android高阶面试题(含答案解析)的朋友————(此处免费打包领取)