Flutter技术解析:Google Fuchsia OS的应用开发方式与价值评估
前言

每当我们评估新技术时,我们问的第一个问题是“它将给我们的业务和客户带来什么价值?”工程师很容易沉迷于闪亮的新事物,但却常常忽视它。事实上,这可能对我们的客户没有任何好处,只会让现有的工作流程变得更加复杂。
Flutter最近相当流行,毕竟是Google出品的。
但我们不是炒作热门话题的媒体,也不是骗你交学费的培训机构。作为真正的跨平台开发者,我们冷静地分析这个东西。
Flutter是Google专为Fuchsia操作系统设计的应用程序开发方法。
Fuchsia OS需要兼容廉价的物联网设备,并且需要降低硬件消耗。为了避免与Oracle的Java提起诉讼,Fuchsia采用了dart语言+flutter界面库。
从设计角度来看,这个方案的性能确实足够高。虽然dart属于大前端范畴,但是dart是像java一样的强类型语言,这使得dart虚拟机可以做很多优化,在性能上超越js。
Dart 曾与 Typescript 较量,js 谁更胜一筹?但遗憾的是它输给了 typescript,chrome 也放弃了构建 dart 虚拟机的计划。
不过,Dart团队并没有解散。几年后,他们在 Flutter 的帮助下再次出现在公众面前。
性能分析与编写方法比较
作为一个界面库(注意,它只是一个界面库,Dart语言是另一个项目),它唯一要做的就是渲染界面。与HTML5不同的是,Flutter界面库甚至没有视频、定位等,它是一个纯粹的排版引擎,绘制文本、按钮、图片等常见界面控件。
该排版引擎的特点是简单、高性能。
三大主流渲染引擎webview、react native/weex、flutter中,复杂度下降,渲染性能提升。 (uni-app有双渲染引擎,webview和weex都内置,开发者可以随意切换)
因此我们需要明确的是,提高性能是有代价的。你想要灵活丰富的CSS3、固定的flex模式布局,还是最简单但高性能的flutter布局?开发便利性和运行性能是不相容的。
同时我们要明白,性能差异并不是因为Google的chrome团队和Android团队的技术不如同公司的flutter团队。但Flutter提供的布局写入方式受到限制,解析速度快,所以渲染也快。不要忘记WebView的布局引擎也是由世界一流的工程师用C编写的。
但这样提升性能的代价是,在布局复杂的界面时,Flutter的代码嵌套到了崩溃的地步。
我们先举个例子,如何使用HTML和flutter实现相同的界面:
小文字
.灰盒{
显示:柔性;
对齐项目:居中;
调整内容:居中;
背景颜色:#e0e0e0; /* 灰色 300 */
宽度:320px;
高度:240像素;
字体:18px
.redbox {
背景颜色:#ef5350; /* 红色 400 */
内边距:16px;
颜色:#ffffff
var container = new Container( // 灰色框
孩子:新中心(
child: new Container( // 红框
孩子:新文本(
“样本文本”,
样式:新的 TextStyle(
颜色: 颜色.白色,
字体大小:18.0,
),
),
装饰: new BoxDecoration(
颜色:颜色.红色[400],
),
填充:新的 EdgeInsets.all(16.0),
),
),
宽度:320.0,
高度:240.0,
颜色:颜色.灰色[300],
);
从代码的编写方式可以看出,Flutter 没有标签和样式,更没有选择器。它从头到尾只有Dart语言。其界面控件是使用Dart代码new创建的。每个控件的样式是new时设置的json参数。
如果我们想要嵌套布局,我们必须不断地在dart中编写children,并在dart中为children设置样式参数。上面的代码仅嵌套一层。在实际开发中,DOM需要多层嵌套。想象一下这段代码。 。 。所以大家都批评dart是“嵌套地狱”。
或者,你可以这样理解,这是一个只有js的浏览器,没有html和css。需要使用js createElement来创建元素,并使用js style方法为每个元素设置样式。反正你不会写html和css代码。前端已经发展成各种MVC等视图逻辑分离架构,也有Vue组件等组件化模式,方便使用各种轮子快速完成界面。你能适应Dart低效的界面开发模式吗?从发展模式来看,这确实是一种倒退。
浏览器的HTML提供了一种分离标签和样式的方法,以及各种选择器,但实际上这也是有代价的。导致webview初始化的时候,必须要启动webkit布局引擎来解析随便写的html和css,还要启动v8或者jscore等js引擎来解析里面的js。
飞镖非常简单。它仅启动一个 dart 引擎并解析严格的 dart 语法。它不会担心如何容忍一些未封闭的标签。不会判断宽度320后面是px还是rem或者动态计算百分比。
比较这两个引擎在初始化时的行为,差异非常巨大。
所以从解析效率来说,flutter肯定是高于webview的。但就编码灵活性而言,Flutter 编写的代码是丑陋且低效的!
Flutter还采用了flex布局的思想,这是一种强嵌套的布局模型,比传统的Web排版引擎嵌套更多。当界面复杂的时候,Flutter的代码需要嵌套几十层,而且每一层元素的json样式都和Dart代码中的元素混在一起,让人崩溃。
有人问是否可以使用预编译的DSL来简化编写方法,让Flutter的开发不那么痛苦。
但这太难了。从严格转向宽松很容易,但从宽松转向严格几乎是不可能的。
这是什么意思?例如,将 Flutter 代码转换为 Web 代码非常简单。 Flutter已经自带了这个功能。但反过来就很难了。
同样,将 typescript 转换为 js 也很容易。相反,也不是绝对不可能,只是会复杂到你宁愿重写一套typescript代码。
Flutter 具有高性能。除了简单、严格之外,另一个特点是逻辑层和视图层统一,运行在同一个Dart虚拟机下。
我们知道rn和weex也是原生渲染的,其性能比webview要高。但如果都是原生渲染的话,怎么会比 Flutter 慢呢?其实并不是原生渲染慢,而是js和原生通信慢。
rn和weex都使用独立的js引擎(iOS是jscore,Android是v8,最新版本的rn已经开始在Android上开发自己的js引擎)。与js和dart相比,性能稍逊一筹。但这不是主要问题。主要问题是rn和weex的js引擎和原生渲染层是两个运行环境。
当js引擎从互联网获取数据并通知原生视图层更新界面时,存在跨环境通信丢失。同样,当用户在屏幕上操作原生视图层并向js引擎发送通知时,也会出现这种通信丢失的情况。
但大多数场景下用户感受不到这种性能差异。影响比较大的场景是手写式的js响应操作来绘制帧动画。
对此,Weex 值得称道的技术是 BindingX,它可以预定义规则,让用户界面在与 Native 层交互时直接通过预定义的规则进行响应,而不需要传递给 js 层。对于需要短时间内来回通信的场景,可以使用BindingX等解决方案。其性能和灵活性都比rn强。
说到 Flutter,它只有一个 Dart 引擎,不存在来回通信带来的性能问题。然而,凡事都有其优点和缺点。虽然Flutter在绘制普通界面时效率很高,但一旦涉及到原生界面,就会遇到更多的问题。
前面说过,flutter只是一个基础的排版引擎,缺乏很多能力。当我们需要在flutter界面上嵌入一个原生的视频播放扩展控件(flutter没有视频播放功能),或者原生的Amap SDK时,那么在拖动视频进度或者拖动地图的时候,Flutter也会引起原生和原生之间的通信。 Dart,导致性能损失。
事实上,由于Flutter是在类似画布的环境中绘制的,因此在Flutter的布局中的某些元素之间嵌入原生控件并不容易,而且存在很多陷阱。
每个人都想要一个像CSS3一样具有灵活编写方式的布局引擎。他们对 React Native 和 weex、flutter 都有要求。殊不知,当这些产品团队实现了CSS3之后,性能优势就不复存在了,相当于又实现了webview。他们不会接受这种毫无意义的要求。
性能良好且合理。客观来说,rn/weex 的原生渲染性能和 flutter 的渲染性能在用户体验上并没有明显的区别。甚至在很多场景下,和webview渲染的小程序没有明显的区别。区别。
我们也简单说一下webview渲染小程序,为什么它有高性能,核心就是预加载。当你点击新页面时,webview就被提前创建好了,不会经历webkit和v8复杂的初始化过程。甚至开发者的js代码也是预加载的。所以当你点击一个新页面时,它的渲染速度与原生应用程序没有什么区别。当然,也有一个缺点,那就是启动慢。微信启动小程序的速度看起来还可以。事实上,微信在启动小程序之前就已经提前初始化了小程序运行环境。
即使是排版引擎,UI库好用吗?
无论是rn还是flutter,都有一个设计非常不中国化。他们在iOS和Android平台上使用了2套ui库。
例如,在flutter中,在iOS上编写按钮时,需要使用CupertinoButton,这是一个iOS风格的控件。在Android上,您需要使用RaishedButton,它是一个Material风格的控件。
rn也是同样的道理。它的官方说法是:一次学习,随处书写。它甚至不敢说:一次编写,随处运行。因为它确实需要开发者写2套代码。
中国的开发者没有这个习惯。中国的每个开发者都采用中性设计来防止用户在更换手机后使用他们的应用程序。
即使在微信安卓版本中,底部的标签也是模仿iOS而不是Material风格(Material风格将底部标签放在顶部并左右滑动。微信曾经有过这样的临时版本,但很快就被删除了,因为用户的投诉)。
是什么原因造成了中国与国外的这种差异呢?
国外Android手机的主界面具有浓厚的Material风格。 Android主界面用户习惯的风格和使用方法。如果启动应用程序后不是这种情况,用户将无法使用它。
Google 多次向 Android 开发者强调,App 必须使用 Material 风格。这实际上是为了防止用户放弃Android的策略设计。
因此,国外开发者的应用在Android上都会遵循Material风格。当然,这个Material风格的App不能在苹果的Appstore上架。
这导致他们默认写了两套UI,所以rn和flutter都针对iOS和Android各有一套UI控件。
但在中国,我们国产的Android Rom根本就不是Material风格的。很多Roms都以模仿iOS体验为卖点。
因此,所有中国App都具有接近iOS的中性风格。中国用户更换手机时,无论是手机操作系统本身还是App的使用都不会造成切换障碍。
rn、flutter等“跨平台”排版引擎的跨平台性对于中国开发者来说已经打了折扣。
事实上,类似于小程序的UI风格可以在iOS和Android上提供良好的体验。无论您使用什么手机,打开小程序都不会有任何问题。
uni-app 默认也有这种通用的 UI 风格。 uni-app的开发者只需要编写一套界面UI即可适应不同手机的用户。它真正做到一次编写,随处运行。
动态的
webview和rn/weex都有一个功能就是可以远程动态加载js代码并更新本地js代码。前端开发者认为动态是自然的,但事实上 Flutter 并不支持。
Flutter有编译优化的概念。如果提供动态支撑,就会影响其性能。
业内有开发者对Flutter进行了改造,使用独立的v8/jscore加载动态JS代码来操作Flutter布局引擎的渲染。看来有些人还在追求这样的计划,闲得让人心疼。
Flutter本来不存在跨环境通信问题,但是引入了js引擎导致通信问题,导致性能下降,包体积增大。最好直接使用rn/weex。
除了flutter之外,rn/weex/uni-app都可以动态热更新。
跨平台排版引擎和跨平台应用开发引擎的区别
有人说他们的应用程序使用了 rn/weex 和 flutter。但他们究竟做了什么?
是整个应用程序都使用它们,还是某个页面使用它们?
跨平台的页面和跨平台的应用程序是两个完全不同的概念。
Webview、rn/weex、flutter 都是渲染引擎。由于HTML5的发展,webview多了一些额外的功能,比如位置服务、多媒体等。然而,rn/weex 和 flutter 实际上只是纯粹的排版引擎,没有任何原生功能。
如果在原生应用中,不涉及原生能力的接口想要跨平台,那么使用这些引擎中的任何一个都可以,而Flutter的性能最高。因此,我们可以看到一些公司尝试使用Flutter来实现App中原生交互较少的单个页面。
但如果你想使用跨平台工具开发一个完整的应用程序,它就不是排版引擎了。它需要一个应用程序开发引擎。
什么是跨平台应用程序开发引擎?不仅排版部分要跨平台,API开发也必须跨平台。
应用开发离不开os或者第三方sdk的能力调用。如果是简单的排版引擎,一旦涉及到os能力和sdk调用,iOS和Android工程师就必须合作编写不同的原生代码,并将它们集成在一起。这不是跨平台的。
Airbnb 是 React Native 框架的倡导者和开发者代表。但他们在 2019 年正式宣布放弃 React Native。
原因是什么?
很简单,React Native 并没有提高 Airbnb 的开发效率,反而降低了他们的效率。
“原本我们只能维护Android和iOS的两套代码,但现在我们必须维护三套(指额外的一套react Native js代码),这让我们很累” - aribnb
开发者选择跨平台开发引擎最初是为了提高效率、降低成本。经过几年的实践,Airbnb发现rn无法实现其使用跨平台引擎的初衷,所以无奈放弃了rn,用原生开发重写。
如果想要真正提高开发效率、降低开发成本,跨平台开发引擎需要提供完整的应用开发平台,包含所有常用的跨平台应用开发能力。对于不常用的部分,提供了插件市场以及不需要原生干预的插件使用方法。
在React Native和Flutter社区中,有很多第三方提供的原生插件,但即使是像Airbnb这样的国外开发者也不满意。更重要的是,对于中国开发者常用的很多场景,相应插件的质量和交叉移植性都很难商业化。
更麻烦的是,如果你不知道如何原生开发,你就无法将这些插件与你的前端代码集成。
uni-app,它的设计目标不是一个跨平台的排版引擎,而是一个跨平台的应用开发引擎。
因此,在uni-app的布局部分,可以选择小程序强化webview引擎和weex引擎,可以根据自己的需求进行切换。在能力层面,uni-app提供了htmlplus API、Native.js、插件市场,解决了基于js的原生能力问题。
uni-app 允许开发人员创建完整的跨平台应用程序,而无需了解本机开发。当遇到非常具体的需求时,开发者还可以去插件市场找人定制一个原生插件。他们还是可以用js来集成,还是可以直接在云端打包。
技术学习成本和难度
rn,要求开发者学习react,精通flex布局,需要原生开发协作。
Flutter要求开发者学习Dart,了解Dart和Flutter的API,精通flex布局,需要原生开发协作。
Weex 已经嵌入到 uni-app 中了,就不单独提了。
uni-app要求开发者学习Vue,了解小程序。
显然uni-app的学习成本太低了。它没有额外的专有技术并使用所有公共技术。
学习成本和难度直接意味着:开发成本、招聘成本、上线速度、上线风险。
另外,dart是否值得学习也是一个很大的问题。
Google 才华横溢的工程师还发明了 go 语言。它确实有很多理论上的优势,但实际上市场的主流仍然是c和c++。
生态
任何发展引擎都离不开生态。
对于国外开发者来说,rn和flutter的生态肯定比uni-app好,比如Facebook登录分享、谷歌地图等。
但对于国内开发商来说,情况却恰恰相反。中国开发者需要全端推送(UniPush集成了iOS、华为、小米、OPPO等众多原创推送),国内各种登录、支付、分享SDK,各种国内地图,各种UI库,以及Echart图表等等都有在uni-app系统中。这方面的生态比rn和flutter丰富很多。
其他端的跨端属性
flutter和rn都支持web技术。但它们仅限于普通的界面布局。当涉及到定位、相机、相册等时,需要单独编写代码。
另外,flutter 的 H5 版本,好吧,作为一个中国开发者,你不会想要一个如此强烈的 Material 风格的 H5 版本。 。 。
更何况这个Material ui库非常大,编译出来的H5版本需要十几MB的大小。
uni-app的H5端包含了完整的能力引擎,其丰富的能力可以直接跨终端使用,风格也是跨终端的。 uni-app的H5引擎大小只有100K,gzip后只剩下30K(不包括vue、vue rooter),比其他工具的引擎大小小很多。
此外,中国也离不开小程序。 RN和Flutter都没有官方支持小程序。由于架构差异较大,国内三方无法很好地将RN代码编译成小程序代码。 uni-app可以是一组代码,可以同时编译成iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、今日头条小程序、QQ小程序。
综上所述
每项技术的诞生都有其背后公司的目的。
任何没有明确公司战略的技术,除非是特别简单的技术,否则都很难商业化,因为公司必须投入大量资源才能商业化。
Flutter诞生的目的是为了Fuchsia OS,在下一个互联网趋势,也就是万物互联的物联网时代,提供一个类似于Android在移动互联网地位的垄断操作系统。
因为谷歌已经明确表示,下一个时代不会采用Android+java路线。
至于Android去Java化,那是Kotlin的使命,与Flutter无关。
跨iOS和Android平台开发并不是谷歌的战略目标。
但万物互联何时到来? Fuchsia OS什么时候开始流行的?这在现实中是一个问号,而在谷歌内部,这只是一个战略储备项目。
一种语言的流行并不是一件简单的事情。它并不会因为有优点而流行起来。它需要合适的时间、地点和人。
6 年前我们就知道 dart 比 js 更好。 Dart 不应该消亡,但要成为主流技术太难了。
同样,我们也知道go比c++好,但是go还是无法上手。
依靠 Flutter 带动 Dart 的普及是不现实的,甚至可能适得其反。跨iOS和Android开发在国外并不是主流市场。这个价值无法创造一个如此难以建立的生态系统。
因此,dart 是否会流行还有一个很大的问号。可能就像go语言一样,会流行但不会流行。
写了这么多,最后总结一下flutter和uni-app的对比:
我们总结一下rn和uni-app的对比
贴个vue、react、react native的百度指数对比。无论是整体体量差距还是发展趋势下滑,都可以明显看出react系统在国内确实不好。
中国开发者过去一直认为:
我的应用中可以使用小程序的webview优化技术吗?现在uni-app已经为您解决了这个问题。 weex 能不能少一些陷阱,多一些 API 和插件?现在uni-app已经为您解决了这个问题。
如果你是一家大公司,资源丰富,并且原生App中的一些页面不需要动态,没有太多原生交互,你可以尝试使用Flutter来实现。但如果大规模使用的话,就会遇到和aribnb一样的问题。维护 3 组代码比维护 2 组代码更糟糕。
如果你开发一个uni-app,使用weex原生渲染,app的性能就足够好了,你会得到开发效率的大幅提升、成本的降低、上线速度快、风险低。
选择跨平台工具而不是原生开发的本质目的不就是为了成本和效率吗?真正能解决你的基本需求的是uni-app。