这里简单回顾一下,在有客户端开发的场景下,为什么又出现了 RN ?

RN 的价值简单来讲就是—— 可接受的页面性能 + 高效开发 + 热更新。

  • 更新:传统的 APP 上架之后,出现了业务 BUG,用户只能去更新 APP,进行 BUG 修复。客户端实现热更新修复 BUG,有多难,可以问问 IOS 的开发同学。大概率猜测,手 Q 和微信,应该还是有方案可以热更新的。但是对很多小厂商这确实是非常艰难的事情。因此,得益于强大的动态化能力 RN 的价值也就完美的体现出来了。

  • 高效:一个 APP 发布上线,Android 和 IOS 同时需要开发两个应用,而 RN 只需要一套代码,就可以运行在双平台上,节省很大的人力成本。并且很多业务线有很强的业务运营诉求,可能会存在很短时间内的多次改版和发布的情况出现,客户端开发的人力瓶颈和发布周期的限制,已经很难满足这样的业务场景了。尤其在一些有损发布的情况下,赶着时间点,带着 BUG 上线的场景,在后续进行增量的修复,再这样的情况下,传统客户端的表现,简直就是灾难性的。

  • 性能:RN 具有优于 H5 的性能体验。毕竟是通过客户端进行的页面渲染,速度上比 WebView 渲染还是要快不少的。这个在 Weex、Hippy、Plato 上都有所体现,虽然低于 Native 的性能,但是在可接受范围。PS:这里的表达,不是描述客户端开发不好。只是单纯从业务角度上看待问题,而把合适的技术放在合适的位置是非常重要的,这也是架构师核心价值之一

回顾了以上三点,我们发现 RN 的出现,有它的必然性。那么回到主题,RN 已经这么优秀了,为什么还要有 Flutter 的存在,有一次向 Ab 哥请教技术成长的时候,Ab 哥提到了很有意思的一个观点,就是您对一项技术了解的深入程度,取决于是否能认清这项技术的局限。 就像人一样,他(她)有多少优点,就会存在多少缺点。没发现,不等于不存在,因为一定存在。因此,顺着这个思路,我们简单的看一下 RN 的问题。

首先,看维护成本,虽然 RN 是一套代码多端运行。但还是需要 IOS 和 Android 开发帮助我们去一个一个的绘制组件,尤其遇到特殊诉求的时候,还要 case by case 的处理,并且随着 IOS 和 Android 系统本身的迭代和升级,以及框架自身发展的历史包袱,我们可能还需要处理很多与原生系统之间的平台差异,修复各种奇奇怪怪的 BUG,这对业务来说是很大的负担。

其次,对性能诉求,无论是产品还是开发同学,对于用户体验的追求,永远都不会停止。RN 存在诸多性能的短板,因此,才会有 Weex 这样的产品出现,去定制化的解决业务场景下的问题。JS 和 Native 的通信,页面的事件监听,复杂动画的渲染和交换成本,都是很大的性能挑战。

最后,在存在更强的业务诉求的时候,人们就不得不去寻找更好的方式去实现。非常存感激的看待谷歌这家公司,都是定位于商业公司,但实际上对世界的影响力上面,公司与公司之间差距还是非常大的。这个课题范围太大,以后有机会可以深度讨论一下。

您看到了上面的描述,为了解决上面这些问题 —— 自绘引擎时代出现了,以 Flutter 为代表的技术方案会应运而生,相信一定不会只有 Flutter 一项跨平台技术出现的,历史总是惊人的相似。其实想到自绘引擎,我最先想到的是那些游戏引擎。那现在又为什么给出 自绘引擎 这样的一个概念呢?H5 是依赖于浏览器渲染,RN 依赖于客户端渲染,而 Flutter 基于 Skia 自己绘制的图形界面。因此,Flutter 才能真正实现跨端!相信在不久的未来,在传统客户端上也能看到 Flutter 的身影,这样才能真正达到多端统一。

最后,我们再简单总结一下有哪些问题:

1、Web 性能差,跟原生 App 存在肉眼可见的差距;

2、React Native 跟 Web 相比,支持的能力非常有限,特定长场景问题,需要三端团队一个一个处理;

3、Web 浏览器的安卓碎片化严重(感谢 X5,腾讯的同学过得相对轻松一些)。

为了解决上面的问题,Flutter 出现了:

一套代码可以运行在两端;

自绘 UI,脱离平台,也可以简单的把它理解为一个浏览器的子集。

铺垫了这么多,就是为了帮助您回忆起技术发展的脉络和技术趋势,可以更好的理解下面即将要表达的文稿,下面我们正式开始介绍 Flutter。

2)Flutter 实现原理Flutter

能介绍的技术点其实非常多,这里找了一些具有代表性的技术项,结合自己的理解跟大家分享一下。包括设计思路、渲染方式、UI 的生命周期。因为这几个点,跟 React 技术栈风格非常相似,以这种思考结构去对比介绍,可以帮助大家更好的理解这项技术本身。

Flutter 整体架构设计

Google 了一下关键词,搜素得到了这张图片,从下向上进行一些描述:

**Embedder:**是操作系统适配层,实现了渲染 Surface 设置,线程设置,以及平台插件等平台相关特性的适配。从这里我们可以看到,Flutter 平台相关特性并不多,这就使得从框架层面保持跨端一致性的成本相对较低。

Flutter Engine:这是一个纯 C++实现的 SDK,其中囊括了 Skia 引擎、Dart 运行时、文字排版引擎等。不过说白了,它就是 Dart 的一个运行时,它可以以 JIT、JITSnapshot 或者 AOT 的模式运行 Dart 代码。在代码调用 dart:ui 库时,提供 dart:ui 库中 Native Binding 实现。 不过别忘了,这个运行时还控制着 VSync 信号的传递、GPU 数据的填充等,并且还负责把客户端的事件传递到运行时中的代码。具体的绘制方式,我们放在后面描述。

Flutter Framework:这是一个纯 Dart 实现的 SDK,类似于 React 在 JavaScript 中的作用。它实现了一套基础库, 用于处理动画、绘图和手势。并且基于绘图封装了一套 UI 组件库,然后根据 Material 和 Cupertino 两种视觉风格区分开来。这个纯 Dart 实现的 SDK 被封装为了一个叫作 dart:ui 的 Dart 库。我们在使用 Flutter 写 App 的时候,直接导入这个库即可使用组件等功能。

PS:虽然很早知道 Flutter,但实际写 Flutter 时间也比较短暂。引擎源码层面,目前也没有深入的涉猎。了解的方式可以通过自己阅读源码,或者找谷歌、阿里、美团、以及我司的开发者帮忙。从技术角度来了解这些,在需要的阶段,不会成为大家的瓶颈。毕竟商业世界充满了壁垒,而应用层面的技术本身是开放的。

3)Flutter 应用层语言 Dart

简单描述一下 JIT 与 AOT:

  • JIT在运行时即时编译,在开发周期中使用,可以动态下发和执行代码,开发测试效率高,但运行速度和执行性能则会因为运行时即时编译受到影响。

  • AOT即提前编译,可以生成被直接执行的二进制代码,运行速度快、执行性能表现好,但每次执行前都需要提前编译,开发测试效率低。

Dart 是什么

它的目标在于成为下一代结构化 Web 开发语言。Dart 发布于 2011 年 10 月 Google 的"GOTO 国际软件开发大会"。是一种基于类编程语言(class-based programminglanguage),在所有浏览器都能够有高性能的运行效率。Chrome 浏览器内置了 DartVM,可以直接高效的运行 dart 代码(2015 年被移出)。支持 Dart 代码转成 Javascript,直接在 Javascript引擎上运行。dart2js

Dart 的特点

  • 开发时 JIT,提升开发效率;发布时 AOT,提升性能。

  • 不会面对 JS 与 Native 之间交互的问题了。

  • Dart 的内存策略,采用多生代算法(与 Node 有一些类似)。

  • 线程模型依旧是单线程 Event Loop 模型,通过 isolate 进行隔离,可以降低开发难度(与 Node 也非常类似)。

  • Dart 的生态,这个跟 Node.js 差距十分明显,npm 还是行业中最活跃的。

  • 而静态语法与排版方式,纯前端入门还是有一定成本。

备注:

1)TS 可以一定程度上帮助 JS 添加一些静态检测,但本质上依旧是无法达成这样的效果;

  1. 关于入门成本这个问题,如果您想深入,我相信这都不会成为问题。关键看是否能为业务和团队带来价值。

Flutter 选择 Dart 的原因

  • 健全的类型系统,同时支持静态类型检查和运行时类型检查。

  • 代码体积优化(TreeShaking),编译时只保留运行时需要调用的代码(不允许反射这样的隐式引用),所以庞大的 Widgets 库不会造成发布体积过大。

  • 丰富的底层库,Dart 自身提供了非常多的库。多生代无锁垃圾回收器,专门为 UI 框架中常见的大量 Widgets 对象创建和销毁优化。

  • 跨平台,iOS 和 Android 共用一套代码。

  • JIT & AOT 运行模式,支持开发时的快速迭代和正式发布后最大程度发挥硬件性能。

  • Native Binding。在 Android 上,v8 的 Native Binding 可以很好地实现,但是 iOS 上的 *JavaScriptCore 不可以,所以如果使用 JavaScript,Flutter 基础框架的代码模式就很难统一了。而 Dart 的 Native Binding 可以很好地通过 Dart Lib 实现。

4)Flutter 实现思路

看到了上面的介绍,这里总结一下 Flutter 的实现思路。它开辟了新的设计理念,实现了真正的跨平台的方案,自研 UI 框架,它的渲染引擎是 Skia 图形库来实现的,而开发语言选择了同时支持 JIT 和 AOT 的 Dart。不仅保证了开发效率,同时也提升了执行效率。由于 Flutter 自绘 UI 的实现方式,因此也尽可能的减少了不同平台之间的差异。也保持和原生应用一样的高性能。因此,Flutter 也是跨平台开发方案中最灵活和彻底的那个,它重写了底层渲染逻辑和上层开发语言的一整套完整解决方案。

彻底跨端:

Flutter 构建了一整套包括底层渲染、顶层设计的全套开发套件。

这样不仅可以保证视图渲染在 Android 和 IOS 上面的高度一致,也可以保证渲染和交互性能(媲美原生应用)。

与现有方案核心区别:

类 RN 方案,JS 开发,Native 渲染。数据通信 bridge;

Hybird 浏览器渲染 + 原生组件绘制;

Flutter 设计自闭环,完成渲染和数据通信。

3、Flutter
的 UI 渲染方案


渲染方案是 Flutter 目前独特的设计形态,就是由于渲染自闭环,才能真正跨平台。谈到 UI 渲染方案,作为前端开发,我们是绕不过现在如火如荼的三大框架的。为什么要谈类 React 方案呢?因为 Flutter 的设计方案,与 React 设计具有一样的思路。在渲染这里我们会谈及控件、渲染原理、以及生命周期。

Flutter 是如何进行页面渲染的呢?传统 Web 是通过浏览器,而 Flutter 是自绘。所谓自绘就是用户界面上 Flutter 自己绘制到界面,无需依赖 IOS 和 Android 原生能力,是通过一个叫做 Skia 引擎进行页面绘图。

1)介绍一下 SkiaSkia

是一个 2D 的绘图引擎库,其前身是一个向量绘图软件,Chrome 和 Android 均采用 Skia 作为绘图引擎。Skia 提供了非常友好的 API,并且在图形转换、文字渲染、位图渲染方面都提供了友好、高效的表现。Skia 是跨平台的,所以可以被嵌入到 Flutter 的 iOS SDK 中,而不用去研究 iOS 闭源的 CoreGraphics / Core Animation。

Skia 是用 C++ 开发的、性能彪悍的 2D 图像绘制引擎,其前身是一个向量绘图软件。Skia 在图形转换、文字渲染、位图渲染方面都表现卓越,并提供了开发者友好的 API。Android 自带了 Skia,所以 Flutter Android SDK 要比 iOS SDK 小很多。正是得益于 Skia 的存在:

  • Flutter 底层的渲染能力得到了统一,不在需要使用做双端适配;

  • 通过 OpenGL、GPU,不需要依赖原生的组件渲染框架。

  • Flutter 可以最大限度的抹平平台差异,提升渲染效率和性能。

2)Flutter 的渲染流程

用户可以看到一张图像展示,至少需要三类介质:CPU、GPU 和 显示器。CPU 负责图像的数据计算,GPU 负责图像数据的渲染,而显示器是最终图片展示的载体。CPU 拿到需要上屏的数据做处理和加工,处理完成之后交给 GPU,GPU 在渲染之后将数据放入帧缓冲区,随后随着控制同步信号 (VSync)以周期性的频率,从缓冲区内读出数据,在显示器上进行图像呈现。而且操作系统就是一个无限循环的机制,不停的重复上面的操作,进行显示器的更新.

Flutter 的渲染整体流程也是这样的, Dart 进行视图数据的合成,然后交给 Skia 引擎进行处理,处理之后再交给 GPU 进行数据合成,然后准备上屏。当一帧图像绘制完毕后准备绘制下一帧时,显示器会发出一个垂直同步信号(VSync),所以 60Hz 的屏幕就会一秒内发出 60 次这样的信号。

3)Flutter 绘制流程

如上图所示,Flutter 渲染流程分为 7 个步骤:

首先是获取到用户的操作,然后你的应用会因此显示一些动画 ;

接着 Flutter 开始构建 Widget 对象。Widget 对象构建完成后进入渲染阶段,这个阶段主要包括三步:

  • 布局元素:决定页面元素在屏幕上的位置和大小;

  • 绘制阶段:将页面元素绘制成它们应有的样式;

  • 合成阶段:按照绘制规则将之前两个步骤的产物组合在一起

最后的光栅化由 Engine 层来完成。

4)布局

布局时 Flutter 深度优先遍历渲染对象树。数据流的传递方式是从上到下传递约束,从下到上传递大小。也就是说,父节点会将自己的约束传递给子节点,子节点根据接收到的约束来计算自己的大小,然后将自己的尺寸返回给父节点。整个过程中,位置信息由父节点来控制,子节点并不关心自己所在的位置,而父节点也不关心子节点具体长什么样子。

为了防止因子节点发生变化而导致的整个控件树重绘,Flutter 加入了一个机制——RelayoutBoundary,在一些特定的情形下 Relayout Boundary 会被自动创建,不需要开发者手动添加。

边界:Flutter 使用边界标记需要重新布局和重新绘制的节点部分,这样就可以避免其他节点被污染或者触发重建。就是控件大小不会影响其他控件时,就没必要重新布局整个控件树。有了这个机制后,无论子树发生什么样的变化,处理范围都只在子树上。

缓存:要提升性能表现,缓存也是少不了的。在 Flutter 中,几乎所有的 Element 都会具有一个 key,这个 key 是唯一的。当子树重建后,只会刷新 key 不同的部分,而节点数据的复用就是依靠 key 来从缓存中取得。

点部分,这样就可以避免其他节点被污染或者触发重建。就是控件大小不会影响其他控件时,就没必要重新布局整个控件树。有了这个机制后,无论子树发生什么样的变化,处理范围都只在子树上。

缓存:要提升性能表现,缓存也是少不了的。在 Flutter 中,几乎所有的 Element 都会具有一个 key,这个 key 是唯一的。当子树重建后,只会刷新 key 不同的部分,而节点数据的复用就是依靠 key 来从缓存中取得。

腾讯官方文档,Flutter全方位深入探索,kotlin语法像Delphi相关推荐

  1. python笔记6-python官方文档之format()格式化详解

    字符串格式化之format() 字符串的格式化是特别特别重要的一个知识点,自己将通过python官方文档来具体总结学习它,整体为如下一篇笔记文章,以备自己后来复习回顾.      一.format() ...

  2. openharmony编译报错ubuntu20.04按照官方文档,hb set报错为OHOS ERROR] Invalid vendor path: /home/openharmony/vendor

    ubuntu20.04按照官方文档,hb set报错为OHOS ERROR] Invalid vendor path: /home/openharmony/vendor 作者:坚果 公众号:" ...

  3. react router官方文档_阿里开源可插拔 React 跨端框架 UmiJS

    点击上方"开发者技术前线",选择"星标" 18:30 在看 真爱 作者:Tamic  |  编辑: 可可 阿里之前开源:阿里闲鱼开源 Flutter 应用框架 ...

  4. 别被官方文档迷惑了!这篇文章帮你详解yarn公平调度

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由@edwinhzhang发表于云+社区专栏 FairScheduler是yarn常用的调度器,但是仅仅参考官方文档,有很多参数和概念文 ...

  5. pythondocumentation_python官方文档

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 方便大家可以更多地了解python查阅到相关函数或者功能的用法. 01搜索引擎首 ...

  6. 微信小程序联盟:官方文档+精品教程+demo集合(12月更新……)

    1:官方工具:https://mp.weixin.qq.com/debug/w ... tml?t=1476434678461 2:简易教程:https://mp.weixin.qq.com/debu ...

  7. python-tkinter 官方文档

    python-tkinter官方文档 防盗声明:在其他网站看到的都是盗版的 本文源地址唯一地址 https://blog.csdn.net/weixin_44331765/article/detail ...

  8. 最新Elasticsearch8.4.3 + Kibana8.4.3在云服务器Centos7.9安装部署(参考官方文档)

    一.前言   最近笔者学习Elasticsearch,官方最新稳定版为 Elasticsearch-8.4.3,想在云服务器上Centos7.9搭建.搭建之路坑多路少啊(指网上的博文教程五花八门,基本 ...

  9. 使用cephadm部署单节点ceph集群,后期可扩容(基于官方文档,靠谱,读起来舒服)

    目录 ceph各种部署工具比较(来自官方文档的翻译,靠谱!) 材料准备 cephadm使用条件 服务器有外网访问能力 服务器没有外网访问能力 安装cephadm cephadm的功能 两种安装方式 基 ...

最新文章

  1. Keras【Deep Learning With Python】更优模型探索Keras实现LSTM
  2. 简单的c语言推箱子程序,完整版本的推箱子小游戏,最简单的纯C语言打造
  3. 图神经网络代码_第一篇:图神经网络(GNN)计算框架绪论
  4. 【Python】全网最新最全Pyecharts可视化教程(一)
  5. 功能强大的云打印组件-开始使用
  6. php随机生成卡密,PHP随机生成不反复的8位卡号(数字)和卡密(字符串)_后端开发...
  7. 基于.Net C# 通信开发-网络调试助手
  8. 2022G3锅炉水处理上岗证题库及答案
  9. java------jdkd的安装与配置变量环境
  10. 南阳oj 韩信点兵
  11. 【安卓基础】Android直接通过路径来操作其他应用的私有目录,可以吗?
  12. 主线程结束子线程会跟着结束吗
  13. 推流(RTSP/RTMP)
  14. 国内首家!网易易盾加固第一时间适配Android Q Beta
  15. 技术文档的写作规范总结
  16. Debug 集子[更新中]
  17. 大数据-hadoop-服务器-网络拓扑
  18. [MIT]微积分重点 第六课 sinx和cosx的导数 学习笔记
  19. 项目交易平台上发布的项目
  20. n个a和m个b的排列

热门文章

  1. 笔记---腾讯云滑块验证码SDK的使用
  2. 将十进制数转化为八进制数
  3. Missing Private key解决方案——IOS证书 .cer 以p12文件
  4. 修改系统环境变量path
  5. 利用scipy.optimize.minimize()求解有约束、非线性规划问题
  6. DIY大神分享:i7 10700k配什么散热
  7. Azkaban——安装指南
  8. uestc 宝贵资源 1265 (水)
  9. 计算机配件的选购标准,计算机配置方案与配件选购
  10. CloudStack初级部署与实例创建