请选择 进入手机版 | 继续访问电脑版

雨林木风

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7|回复: 0

Android架构思考(模块化、多进程)

[复制链接]

9806

主题

9813

帖子

3万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
30029
发表于 2021-2-16 07:59:51 | 显示全部楼层 |阅读模式
  ,同时有些项目(好比咱们公司)还伴跟着子操纵独立包装增添,影子操纵独立揭晓等等需求,从新调理架构迫正在眉睫。这日,咱们就来聊聊模块化(组件化),这篇著作同时也是我这几年,对项目架构的知道。
  当咱们最发轫做Android项主意时刻,大大批人都是没思量项目架构的,咱们先上一张图。

  这个分包组织有没有很熟谙,百般组件都码正在一个包里,全体没有层级组织,营业、界面、
  逻辑都耦合正在沿道。这是我12岁终刚发轫初学Android的时刻开采的一个小项目,半年后,来了个小伙伴,然后咱们沿道开采,然后天天由于谁修削了谁的代码打的不成开交。
  再其后开采App,职员比之前众了,因此不行依照以前那样了,务必得重构。于是我把公用的代码提取出来筑制成SDK底子库,把独立的功效封装成Library包,差异营业通过分包组织分到差异module下,组内每人开采自身的module。刚发轫都还轻松加欣忭,并行开采啥的,一片亲善的场景,如下图。

  跟着光阴推移,咱们的App迭代了几个版本,这几个版本也没什么此外,概略来讲便是三件事项:

  可能看到,跟着几个版本营业的添加,各个营业某块之间耦合愈发紧张,导致代码很难爱护,更新,更别说写测试代码了。固然后期引入联合播送编制,必然水准改进了模块间彼此援用的题目,然则限度性和耦合性仍是很高,没措施根治这个题目。这个架构做到结尾,扩展性和可爱护性都是很差,而且难以测试,因此最终被史乘的历程所扬弃。
  光阴很疾就来到了2015年,这一年动态加载、热修复很火,360、阿里等至公司先后开源了自身的处置计划,如droidplugin、andfix等。正在查究了一圈察觉,这些本领对架构升级有必然的助助,更加是droidplugin的加载apk的思思,能很好地处置耦合度高、手腕数高出65535、动态修复bug等题目,可是因为项目自身不是很大,而且没有特意的人来爱护架构,因此结尾放弃了功效重大、然则题目也同样众的插件化,退而求其次,挑选了诈欺道由机制来完成组件化解耦。
  合于道由机制,熟谙iOS开采的诤友或许并不不懂,正在iOS上有良众架构计划都是采用道由机制来光阴模块之间的解耦的,好比VIPER(View Interactor Presenter Entity Routing)思思等等。本来思绪都是相像的,Android上面组件化也是通过公用的道由,来完成模块与模块之间的远隔。

  这几个Module都援用了Common库,同时Main Module还援用了A、B、N这几个Module,原委云云的解决之后,全面的Module之间的彼此挪用就都消灭了,耦合性低落,全面的通讯联合都交给Router来解决分发,而注册事务则交由Main Module去实行初始化。这个架构想思本来和Binder的思思很相像,采用C/S形式,模块之间远隔,数据通过共享区域实行通报。模块与模块之间只宣泄对外怒放的Action,因此也具备面向接口编程思思。
  图中的血色矩形代外的是举措Action,Action是简直的实行类,其内部的invoke手腕是简直实行的代码逻辑。假如涉及到并发操作的话,可能正在invoke手腕内参与锁,或者直接正在invoke手腕上加上synchronized描摹。
  图中的黄色矩形代外的是供应商Provider,每个Provider中包括1个或众个Action,其内部的数据组织以HashMap来存储Action。最先HashMap盘查的光阴庞大度是O(1),适宜咱们对换用速率上的哀求,其次,因为咱们是联合实行注册,因此正在写入时并不存正在并发线程并发题目,正在读取时,并发题目则交由Action的invoke去简直解决。正在每一个Module内都邑有1个或众个供应商Provider(假如不包括Provider,那么这个Module将无法为其他Module供应任事)。
  途中蓝色矩形代外的是道由Router,每个Router中包括众个Provider,其内部的数据组织也是以HashMap来存储Provider,道理也和Provider是相通的。之因此用了两次HashMap,有两点出处,一个是由于云云做,禁止易导致Action的重名,另一个是由于正在注册的时刻,只注册Provider会省略注册代码,更易读。而且因为HashMap的盘查光阴庞大度是O(1),因此两次查找不会奢侈太众光阴。当查找不到对应Action的时刻,Router会天生一个ErrorAction,会告之挪用者没有找到对应的Action,由挪用者来定夺接下来若何解决。

  全面的Module之间的彼此依赖没有了,咱们可能正在主app中,废止恣意的Module援用而不影响完全App的编译及运转。

  如图所示,咱们废止了对Module N的依赖,完全操纵如故可能平静运转,碰到挪用Module N的地方,会返回Not Found提示,现实开采中可能遵循需求做简直的解决。
  因为每个Module并不依赖其他的Module,因此正在开采历程中,咱们只针对自身的模块实行开采,并可能筑一个测试App来实行白盒测试。

  合于复用性这块。作家所处的行业是招商投资这块,这个行业必要缠绕主营业开采良众影子APP,将掩盖面增添(有点相像58-58租房、58聘请,美团-美团外卖等)。这个时刻,这个架构的复用性就外现出来了,咱们可能把营业实行拆分,然后写一个包装App,就可能天生一个独立的影子APP,这个影子APP用到哪些Module就援用哪些就可能了,开采缓慢,而且后期Module营业有蜕化,也不必更改全面的代码,省略了代码的复制。好比咱们就一经把IM模块和投资讨论模块独立拿出来,写了少许界面和样式,就天生了“招商经纪人”App。
  整套架构很相像Git的Branch思思,基于主线,分支独立开采,结尾再回归主线这种思绪。这里只是思绪和branch形似,现实的开采历程中,咱们每个module可能是一个branch,也可能是一个栈房。每个模块都必要自身有独立的版本掌握,便于题目治理及溯源。主项目对各个模块的援用可能是直接援用,也可能是导出aar援用,或者是上传JCenter Maven等等方法。可是思绪是联合的:承继大家-独立开采-主线新增

  必要贯注的是,咱们的Module A,不必要CommonBaseLibrary中的大家资源,因此没有援用CommonBaseLibrary,然则现实其他仍是可能被其他模块所挪用,由于它内部有Router。
  跟着项主意一直增添,App正在运转时的内存损耗也正在一直添加,况且有时线上的BUG也会导致完全溃散。为了包管优良的用户体验,省略对编制资源的损耗,咱们发轫思量采纳众历程从新架构圭外,通过按需加载,实时开释,抵达优化的主意。
  众历程的便宜和操纵场景,之前正在《Android众历程操纵场景》中也做过先容,概略便宜有这么几个:
  、Action,是注册给后台Router的。当你正在前台历程挪用的时刻,基础挪用不到其他历程的Action。处置计划本来处置的手腕也并不庞大。原先的道由编制还可能接续操纵,咱们可能
  称之为当地道由LocalRouter,现正在,咱们必要供应一个IPS、DNS供应商,那就创筑一个历程,该历程的感化便是注册道由,链接道由,转发报文,咱们称之为广域道由WideRouter。咱们先来看下道由相联架构图

  如图所示,竖直目标上,每一列,代外一个历程,通过虚线分开,分离有Process WideRouter、Process Main、Process A、···、Process N这些历程。浅黄色的代外
  ,实行事宜下发。那么现正在正在外面加了一层WideRouter,那么咱们再加一层Domain,Domain对应的是Android操纵内,各个历程的历程名。平凡状况下,假如事宜是正在统一历程下,那么就相像于局域网内部事宜通报,不必要通过WideRouter,直接内部依照之前的道由逻辑实行转发,假如不正在相像历程内,就由WideRouter实行历程间通讯,抵达跨历程挪用的后果。事宜苦求RouterRequest可能写成两种,

  、Action去跨历程查找是否是异步圭外。假如是异步圭外,那么咱们直接天生RouterResponse(Step13),而且,将Step14-Step24联合封装成Future,放正在RouterResponse中,直接返回。假如是同步圭外,那么就正在如今哨法内实行Step14-Step24,将返回结果放入RouterResponse内(Step25),直接返回。这么做的主意是,咱们的道由挪用手腕route(RouterRequest)默认是同步手腕,不耗时的,可能直接正在主线程里挪用而褂讪成雍塞,褂讪成ANR。假如挪用的方向Action是异步的,那么可能诈欺Java的FutureTask道理,挪用RouterResponse的get()手腕,获取结果。这个get()手腕有或许是耗时的,是否耗时,取决于RouterResponse.isAsync的值是否是true。至于当地事宜分发,仍是与之前的Router形式,从Step17到Step21,都是咱们上文中,单历程同步Router分发机制,没有作任何变更。众历程Application逻辑分发
  正在众历程中,每启动一个新的历程,都邑从新创筑一次Application,因此,咱们必要把各个历程的Application逻辑剥离出来,然后遵循差异的

  注册到Application中,然后,Application会遵循注册时的历程名新闻实行筛选,挑选相像历程名的
  手腕,该手腕可能使本历程与WideRouter实行解绑,然后咱们正在手动合掉历程内的其他组件,结尾挪用System.exit(),抵达开释内存的主意。合理的开释内存,能有用的改进用户体验。小结这篇著作简略讲了一下作家这几年对Android架构的知道。本来本文中没有什么很深的本领点,人人是少许策画形式,架构想思。这套框比起至公司的少许卓绝的动态更新、编译分包、apk插件化加载,仍是方便良众的,更适合中小型操纵。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

|appname
快速回复 返回顶部 返回列表