我对移动端架构的思考

本文由玉刚说写做平台提供写做赞助前端

原做者:Mr.Sreact

版权声明:本文版权归微信公众号玉刚说全部,未经许可,不得以任何形式转载android

架构就像是一场进化史,根据不一样时期的需求,演变出不一样的架构,车轮滚滚,到今天,移动端框架百花齐放,让人应接不暇。可是其中的本质是磨灭不了的,换言之根本没有磨灭而是隐藏到了人们所看不到的地方,可是依旧发挥着不可或缺的做用。ios

为何须要架构?数据库

  • 一个Activity走天下,包含各类模块和功能
  • 臃肿类太多
  • 不一样功能,不一样层次拎不清楚,混合在一块儿
  • 重复代码太多,复用性为差
  • 没法协做开发,
  • 耦合严重,bug太多 等等

当咱们新进一个公司,接受别人的项目的时候,基本都会说句MMP,SHI同样的代码啊,啥玩意啊,搞得什么啊。编程

我擦,我就改了一个参数,怎么全乱套了,一个功能怎么天上地下都须要改啊。服务器

没有经受过痛苦的人,是不会想了解架构的,只有痛苦过的人,才会急切的了解架构,好好作人,不做孽。微信

进化1.0 MVC架构

人们刚接触编程,相信第一个遇到的框架就是MVC,无论你经意仍是不经意写出来的Android程序他就是MVC框架,只不过是MVC框架的某一个变种(最混乱的那种)。Android系统自己就根据MVC建造的。并发

  • XML的View层
  • Activity/Fragment的Controller层
  • 数据Model层。

咱们编写程序刚开始应该是这种结构

image.png

View层和Controller交织在一块儿。在Activity里面处理各类事件和逻辑,界面的显示和更新都在这里,除了按功能分出去的模块外,能在Activity里面写的都会堆在这里面,代码经常达到上千行,别说别人,本身再回到头看的时候也是头皮发发麻。

因此咱们开始试着学Android系统的MVC来梳理代码。固然每一个人从众理解的也不大同样。 无论是单向依赖仍是双向依赖都是为了把处理的职责交给Controller,这一点是不变的,因此无论你用的是哪种形式都是不打紧的,没有对与错。根据本身的需求选择最适合的一种依赖关系。

image.png

优势:

因为MVC很好的分离了视图层和业务层,因此它具备如下优势

  • 耦合性低
  • 开发速度快
  • 可维护性高
  • 易于理解
缺点:
  • 因为MVC的设计思想是从Model出发,而没有考虑到View端的复杂性,这样致使的问题是Model难以符合复杂多变的View端变化。致使Model的做用很小,而不少View层的职责也转移到了Controller层。Controller变得臃肿不堪。耦合性也变高了。
  • 测试困难

MVC使用的误区

其实我在刚开始编程的时候,

误区一:一度认为Model就是实体类(Entity)

正解:是MVC的Model应该有两个功能:

  • 处理业务逻辑
  • 提供View显示的数据
误区二:把业务逻辑所有放在Controller端

正解:Model也会处理业务逻辑

这两个误区其实也和MVC的构成有关系,很容易让人误解,可是本质上仍是不理解MVC,特别是对Model的做用不明白。

其实Model在MVC框架里面的做用不只仅是Entry,Model在MVC中起着很重要的做用,它更应该是业务逻辑的真正实现层,而Controller层更应该做为一个桥接的做用,把View的求情转发给Model,再把Model处理结束的消息告诉View。这样作也就是界面和代码(逻辑)分离。

进化2.0 MVP

可是踏入误区的人太多了,你们都在Activity里面处理逻辑由于太方便了(写的很爽)。 可是这样以后,咱们Activity的职责太多了,耦合也严重,因此咱们就想着怎么能给Activity减负,同时把耦合也降下来,因此就想找个哥们来替Activity分担的责任,你们最后都只有一个责任,各层关系也相对好理解,你们照着这个方式写,那多好,不用加班,每天都很快乐。

既然Activty这么愿意和View搞到一块儿(解耦过高了),那么就让他们俩在一块儿(在一块儿,在一块儿,在一块儿),共同负责View,咱们在招聘一个职业经理人(Presenter)来处理事务,有啥事都找Presenter,你看着多方便啊,MVP是一个真正意义上的隔离View的细节和复杂性的模式

image.png

至于虚线的部分,这个和楼上的MVC的虚线同样,每一个人的理解不一样,状况不一样,选择合适的就好,不用纠结谁对对错,本质不变就能够的。

这样就简单多了,Activity和View两人各类腻歪秀恩爱,各层的关系也一目了然,你们各干各的事情,想要什么和Presenter说一声,有啥事情Presenter也会汇报,简直爽的不要不要的。Presenter也会处理和View层的交互,Presenter在手天下我有。

优势:

一、模型与视图彻底分离(就像牛郎和和织女隔了一个银河,每次都须要靠燕子来传信,好可怜~~)

二、能够更高效地使用模型,由于全部的交互都发生在一个地方——Presenter内部

三、(Presener的复用)一个Presener能够用于多个视图(View),而不须要改变Presenter的逻辑。视图(View)的变化比模型(Model)的变化更频繁的多 ,因此这样超级方便。

四、(View的复用)View能够进行组件化。在MVP当中,View不依赖Model。这样就可让View从特定的业务场景中脱离出来,能够说View能够作到对业务逻辑彻底无知。它只须要提供一系列接口提供给上层操做。这样就能够作高度可复用的View组件。

五、更容易单元测试

缺点:

一、因为对视图的渲染放在了Presenter中,因此视图View和Presenter的交互会过于频繁。特别是须要修改视图的时候,Presenter也须要跟着修改,很麻烦。

二、Presenter中除了业务逻辑之外,还有大量的View->Model,Model->View的手动同步逻辑,形成Presenter比较笨重,维护起来会比较困难。

三、其实总的来讲就是结构很清晰,业务逻辑也很明白,耦合低,可是就是本身写的麻烦,Presenter很差维护,工做量太大,太笨重,有点像MVC中的Activity了,职责太多了。也能够把这三个缺点总结成一句话,麻烦,尾大不掉。

进化3.0 MVVM

可是吧,大家爽了Presenter可就累坏了,大事小事都要通过Presenter,就连放个屁也要Presenter来扒裤子,日子过得久了,Presenter总会有意见啊,不带这么使唤人的。

咱们就想啊,之前过多的依赖Activity形成结构混乱,耦合过高,后来有了Presenter,虽然耦合大大下降,可是仍是过于依赖Presenter,为啥总会过于依赖某一个东西呢,就不能你们都干点活,耦合性也不高的吗?就不能你们有事相互通知吗?非要那么懒依赖别人吗?总要有点正能量吧。那么咱们就把Presenter辞退,引入了一个新的小伙伴VM(ViewModel即 Model of View)它即包含了Modle也有View的状态。

MVVM模式中,一个ViewModel和一个View匹配,它没有MVP中的IView接口,而是彻底的和View绑定,全部View中的修改变化,都会自动更新到ViewModel中,同时ViewModel的任何变化也会自动同步到View上显示。

这种自动同步的缘由其实就是是ViewModel中的属性都实现了observable这样的接口,也就是说当使用属性的set的方法,都会同时触发属性修改的事件,使绑定的UI自动刷新。

在android中DataBinding帮助咱们实现MVVM,在XML进行数据绑定,增长了XML的重量,再也不像之前那样仅仅是布局,均衡了各部分的职责。

因此MVVM比MVP更升级一步,在MVP中,V是接口IView, 解决对于界面UI的耦合; 而MVVM干脆直接使用ViewModel和UI无缝结合, ViewModel直接就能表明UI.

image.png

优势:

一、解决了MVP大量的手动View和Model同步的问题,提供双向绑定机制。提升了代码的可维护性。大大方便了开发者。(只有试过才知道有多方便)

二、简化测试。

三、响应式编程更方便。

缺点:

一、过于简单的图形界面显得大材小用(让开发者麻烦的都是缺点)

二、视图状态较多,ViewModel的构建和维护的成本都会比较高。

三、数据绑定的声明是指令式地写在View的模版当中的,这些内容是没办法去打断点debug的。(这是很碉堡的,只能本身细心了)

进化4.0 CLEAN

进化了一代有一点,做为东家的谷歌坐不住了,给不给我面子了,来来来,我给大家一个终结的,Clean? WTF?这个洋葱一个的家伙是谁?再给你一个圈就是五环了~~四个圈圈了不得啊?

image.png

官方的话说来就是:独立

  • 独立于框架。该体系结构不依赖于某些特征库软件库的存在。这容许您将此类框架用做工具,而没必要将您的系统塞入其有限的约束中。 可测试。能够在没有UI,数据库,Web服务器或任何其余外部元素的状况下测试业务规则。
  • 独立于UI。UI能够轻松更改,而无需更改系统的其他部分。例如,可使用控制台UI替换Web UI,而无需更改业务规则。
  • 独立于数据库。您能够换掉Oracle或SQL Server,用于Mongo,BigTable,CouchDB或其余东西。您的业​​务规则未绑定到数据库。
  • 独立于任何外部机构。事实上,您的业务规则根本不了解外部世界。
依赖规则:

同心圆表明软件的不一样领域。通常来讲,你走的越远,软件就越高。外圈是机制。内圈是政策。

使这种架构工做的首要规则是依赖规则。此规则代表源代码依赖项只能指向内部。内圈中没有任何东西能够对外圈中的某些东西一无所知。特别是,内圈中的代码不得说起在外圈中声明的内容的名称。这包括功能,类。变量或任何其余命名的软件实体。外圈中使用的数据格式不该该被内圈使用,特别是若是这些格式是由外圈中的框架生成的话。咱们不但愿外圈中的任何东西影响内圈。

官方的话就是绕,其实就是依赖是能向里依赖,白话就是内圈向外圈提供服务,好比你去食堂吃饭,选择不一样的窗口,对着里面喊到给我来一份鱼香肉丝。你不用管里面的师傅是否是昨天那一个,也不用管里面的菜是否是昨天的那个口味,你只管你的目的是来一份鱼香肉丝就能够了,里面的菜和师傅,也不用管你是谁,是否是个漂亮的MM,他们只管本身事情,对他们圈外的不依赖,反正你依赖我就能够了。

image.png

Clean将核心业务(Domain层)、UI相关(Presenter层)以及数据加载(Data层)彼此独立开来,不一样的层之间由接口依次链接起来,但却又彼此不了解彼此的具体实现。

优势:

一、代码复用性更高 二、更易于测试 三、耦合度更小

缺点:

一、学习难度大(容易懵逼) 二、代码量大(一个小Demo都够你写一壶了)

从MVC->MVP->MVVM->MVP-Clean 后者解决了前者遗留的问题,把前者的缺点优化成了优势。一代更比一代强,可是都是须要代价的,学习成本更高,更加规范,可是并不必定就谁比谁更好,只有谁更适合你的项目,都有优劣,怎么选择须要靠本身了。 其实MVX系列的本质一直未变:

  • 关注点分离原则
  • 高内聚低耦合原则

同时也但愿适度设计,不要太过追求某一点。会得不偿失。找到最经济的方案才是王道,也能够多种方案配合一块儿配合。

image.png

如何可以更好的将多种架构表如今一款APP里面呢?对!组件化。

组件化

image.png

组件化开发就是将一个app分红多个模块,每一个模块都是一个组件(Module),开发的过程当中咱们可让这些组件相互依赖或者单独调试部分组件等,可是最终发布的时候是将这些组件合并统一成一个apk,这就是组件化开发。

不一样的Module咱们根据职责划分选择不一样的架构,能够最经济的开发一款APP。

image.png

目前成熟的方案有阿里的ARouter,经过路由的方式进行通讯,感兴趣的同窗能够学习下。

优势

一、低耦合 二、能够针对测试(下降测试成本) 三、复用性强 四、支持并行开发 五、适合使用多进程 六、减少编译时间

缺点

一、不适合小型应用或者独立开发 二、各组件开发人员联调,开发进度不一致等问题

应用场景

假如一个app用户量很大,业务丰富,好比某宝,很明显不是一个小团队能够开发的了的,若是不分模块的话,工程的复杂度就太大了,编译时间估计半天都完不成,维护更不用说了,简直不是人干的了。因此很适合分模块来开发。各个模块的耦合性也能降到最低,不至于一个模块有问题,牵连别的模块。编译时间也会大大减少。每一个模块至关于一个小APP,更容易灵活的编译,编写。测试也只须要测试本模块,最后联调总体就能够了。因此说业务越复杂,组件化越有优点。

小结

移动端架构的差别化体如今通讯机制上。通讯机制主要分为3种: 1) 对象持有 2) 接口持有 3) 路由

对象持有最简单,可是解耦率最低; 接口持有较为复杂,实现解耦的需求,可是解耦不完全,相互持有交互方的接口; 路由机制能够实现彻底解耦,实现组件化。

完了吗?不不不~~移动端不只仅Android和iOS,还有前端,上面仅仅是MVX的进化史,同时还有不一样分支的进化。

当下移动端的趋势,愈来愈向大前端靠拢了,Android的道友们也愈来愈瑟瑟发抖,看到RN,Flutter等等的兴起,愈来愈以为仅仅学习Android是不够的,还要学习跨平台,大前端的知识。俗话说他山之石能够攻玉,咱们对架构的思考也是如此,不能仅限于本身的一亩三分地,也要学习下友军的套路。

这类通常都是响应式视图的系统,MVVM就是个响应式,因此其实都是有联系的。

进化 5.0 Flutter/ReatNative

  • Flutter 是Google用以帮助开发者在Ios和Android两个平台开发高质量原生应用的全新移动UI框架,也是听说要把Android替换掉的一个恐怖存在(目前如今仍是个弱鸡)

  • ReactNative 让开发者使用 JavaScript 和 React 编写应用,利用相同的核心代码就能够建立 Web,iOS 和 Android 平台的原生应用。React Native 的宗旨是,学习一次,高效编写跨平台原生应用。

ReatNative

JS 开发者能够用相似DOM编程模型就能够开发原生APP,画UI只须要画到virtual DOM 中,不须要特别关心具体的平台, RN 会把应用的JS代码编译成一个js文件,RN的总体框架目标就是为了解释运行这个js 脚本文件,经过bridge 传递到native , 而后根据数据属性设置各个对应的真实native的View。

image.png

RN官方给的框架是Flux:

image.png

  • action 封装请求
  • dispatcher 注册处理器、分发请求
  • store 是处理器,处理业务逻辑,保存数据
  • view 根据store提供的数据进行展示;接受用户的输入并发出action请求。

解耦很细,作一个功能会涉及不少地方,因此人们对于这个官方架构进行简化,因而有了Reflux。

Reflux:

Reflux.png
这个三层框架就大大简化了flux的复杂交互。无论是面向对象仍是面向状态,其实本质上是一致的。三层框架可以很好处理视图,数据,事件,逻辑的问题。

咱们也能够参考另一种架构Redux。

Redux:

Redux.png
咱们能够看出 其实也是分为三层,组件,Store,Action。组件绑定这Action和state,store reducer都是页面单例,易于管理。action为请求dto对象,是请求类型,请求数据的载体,reducer是处理请求的方法。不容许有状态,必须是纯方法。必须严格遵照输入输出,中间不容许有异步调用。不容许对state直接进行修改,要想修改必须返回新对象。

这就是面向状态编程

react的组件只关注数据的最终状态,数据是怎么产生的并不关心。这个是RN的核心思想。

  • 优势 一、提高产品迭代速度,APP迭代周期变短 二、减小研发成本(可不,ios和android均可如下岗了) 三、提高开发测试效率(不用双端两套代码分开测试了)

  • 缺点 一、原生有些功能实现不了或者说很复杂 二、须要掌握IOS和Android的知识,我的学习成本高 三、须要兼容IOS和Android(很苦逼)

Flutter

今年谷歌推出了Flutter的Beta版本,离正式的出生愈来愈近了。咱们来看看这个新同窗吧。

Flutter主要解决了移动开发中的两个重要问题,一是原生应用程序的性能与平台的集成;二是提供多平台、可移植的UI工具包支持高效应用开发。

和RN的跨平台思想不一样

RN是将一种设计理念延伸到两个平台,而Flutter则实现了一套代码,部署多个平台。解决了RN开发须要IOS和Android基础的窘迫和成本。在Flutter中,每一个应用程序都是Widget,这点和其余的应用框架不同,Flutter的对象模型是统一的,也就是控件。

Flutter 基本上就是一个 V(View),响应式视图,它能够是无状态或有状态的 widget,就连 AppCompatActivity 也是一个 widget。是否是很过度?简单到粗暴。采用widget 和 state分离 ,好比咱们在原生里大量重复代码来管理 Activity 的生命周期。可是在 Flutter 中,这是不须要的,从设计的角度就解决了这个问题。就像LifeCycles也是这种思想,解决了生命周期的问题。

对于这种面向状态编程的思想,架构和RN是相似,同时咱们也期待Google的官方架构指导的出现,会不会有更多的惊喜呢?

image.png
优势 一、响应式视图,不须要JavaScript的桥接器 二、性能更好,兼容性更好 三、代码将AOT编译为本机(ARM)代码 四、美观,可定制的UI组件,开发人员彻底控制UI组件和布局 五、热从新加载

缺点 一、包体很大须要打包本身的SDK 二、占用内存空间大 三、启动时间很慢 四、流畅性和原生有差距

不过由于FLutter还没与正式出版,相信FLutter会解决这些缺点的。

RN和Flutter差异:

对于这二者系统架构的区别 这里有两张图:

Flutter.png
ReatNative.png
咱们能够看出来 主要差异就是Widgets的差异,还有Bridge中间层的区别,Flutter从理论上的速度要别RN高不少,没有了中间层的倒转,有本身的Widgets能够保证IOS和android上的统一。

实现跨平台的这两种方式也是架构设计的体现,Bridge有没有和Presenter很类似,链接着js和系统。RN是将一种设计理念延伸到两个平台,而Flutter则实现了一套代码,部署多个平台。

不一样的设计思想,会走向不一样的路,究竟是哪种走的更好,这个可能就须要随着时间去检验了,虽然理论上FLutter要比RN好不少,可是如今的显示很残酷。不过FLutter才是Beta版本,潜力很是大。

image.png

写在最后

本文把目前移动端主流的架构顺了一遍,也是我本身对架构认识的一个时间轴,从刚开始的胡乱编写,到后来有些章法,不过仍是对框架的领悟很浅,确定有不少谬论错轮,但愿以我我的对架构的思考能够抛砖引玉,若是能够给你一些帮助,那是极好的一件事情了。

无论是RN仍是Flutter,亦或是原生的IOS和Android,其实他们本质编程思想是一致,一样,随着更多更方便的框架出来,咱们的理解能力和学习能力受到了很大的挑战,不少同窗都说学不动,可是事实上技术的更新换代远比咱们学习新知识要快,每每咱们刚学会这个,又会出了另一个,咱们只要掌握了它的核心思想,就不会那么累和无奈了。

这就是技和道的差异,经过技最终掌握道,而不是以技学技,那样没有终点。

咱们在实际中如何选择架构,其实这个的因素不少,最关键的是一个经济,好比项目时间比较短,仍是独立开发,咱们可能就要用MVC了,或者说应用的功能相对简单,也会取用MVC,至于MVP,或者MVVM,CLEAN,这个对于大型开发,特别是协做开发,有着很大的帮助。由于咱们工做不只仅是技术,还有项目周期,老板的喜爱,历史遗留问题,因此选择最经济的一个,而不是选择那个公认最好的那个。

移动端的趋势愈来愈走向统一了,咱们发现愈来愈多的公司,须要大前端的人才,因此要一直学习,创造时代的人都没有说累,咱们跟着学习的人更不该该喊累,没有学不动,只有不想学。同时欢迎你们来刚哥的知识星球,一块儿激励,一块儿砥砺前行。

参考:

React Native运行原理解析 https://blog.csdn.net/xiangzhihong8/article/details/52623852

React Native vs. Flutter 评测 https://mp.weixin.qq.com/s/Or28Gf71wuJrCUP0lKGpGg

ReactNative的组件架构设计 http://react-china.org/t/reactnative/3486

为安卓开发者介绍的移动开发框架 Flutter https://blog.csdn.net/Px01Ih8/article/details/79683595

欢迎关注个人微信公众号,接收第一手技术干货
相关文章
相关标签/搜索