本文由 IMWeb 首发于 IMWeb 社区网站 imweb.io。点击阅读原文查看 IMWeb 社区更多精彩文章。前端
前言
react
腾讯 OED 的客户端团队在 2019 年上半年 ,就已经把 Flutter 落地到 企鹅辅导的业务中了。今年咱们又一块儿去上海参加了 2019 年谷歌开发者大会,碰见了更多的 Flutter 开发者,此次体验比第一次去的时候感受熟悉了不少。但愿将来有机会把他们邀请来深圳,进行一些 Flutter 的技术分享。这次开发者大会又恰逢 Flutter to Web 也已经正式合入 Master,那么,前端同窗是否能够趁着这股东风一块儿参与到 Flutter 的协同开发中呢,我想这问题会困扰着不少人?若是您有好的想法,能够在留言区参与评论。git
本文不是一篇 Flutter 详细的学习教程,更像是一个概览,用尽量平实的语言和对比的思路去描述它。本着依旧从前端同窗的角度出发,去理解一项新的技术,但又不限于前端技术自己。但愿您能经过这篇文章相对全面的理解 Flutter 这项技术自己。特别感谢领导的鼓励和支持,让我有机会去学习和理解 Flutter 框架,由于相对我而言,OED 的客户端团队的同窗经验会远超于我,他们已经完整经历了业务从 0 到 1 的过程,这是一种很是有意思的体验。github
在谈及 Flutter 以前,咱们仍是要先简单回顾一下,客户端的上一次技术革新 —— React Native(此后简称 RN)。相信很是多的团队都有去落地实践 RN 的机会,不少 APP 的首屏渲染方案都是用 RN 技术栈进行的。咱们本身的产品 企鹅辅导 和 腾讯课堂 内的应用也是同样。web
这里简单回顾一下,在有客户端开发的场景下,为何又出现了 RN ?算法
RN 的价值简单来说就是 —— 可接受的页面性能 + 高效开发 + 热更新。npm
更新:传统的 APP 上架以后,出现了业务 BUG,用户只能去更新 APP,进行 BUG 修复。客户端实现热更新修复 BUG,有多难,能够问问 IOS 的开发同窗。大几率猜想,手 Q 和微信,应该仍是有方案能够热更新的。可是对不少小厂商这确实是很是艰难的事情。所以,得益于强大的动态化能力 RN 的价值也就完美的体现出来了。编程
高效:一个 APP 发布上线,Android 和 IOS 同时须要开发两个应用,而 RN 只须要一套代码,就能够运行在双平台上,节省很大的人力成本。而且不少业务线有很强的业务运营诉求,可能会存在很短期内的屡次改版和发布的状况出现,客户端开发的人力瓶颈和发布周期的限制,已经很难知足这样的业务场景了。尤为在一些有损发布的状况下,赶着时间点,带着 BUG 上线的场景,在后续进行增量的修复,再这样的状况下,传统客户端的表现,简直就是灾难性的。浏览器
性能:RN 具备优于 H5 的性能体验。毕竟是经过客户端进行的页面渲染,速度上比 WebView 渲染仍是要快很多的。这个在 Weex、Hippy 上都有所体现,虽然低于 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 的身影,这样才能真正达到多端统一。想起了一句话 ~ 思路决定出路。
最后,咱们再简单总结一下有哪些问题:
一、Web 性能差,跟原生 App 存在肉眼可见的差距;
二、React Native 跟 Web 相比,支持的能力很是有限,特定长场景问题,须要三端团队一个一个处理;
三、Web 浏览器的安卓碎片化严重(感谢 X5,腾讯的同窗过得相对轻松一些)。
为了解决上面的问题,Flutter 出现了:
一套代码能够运行在两端;自绘 UI,脱离平台,也能够简单的把它理解为一个浏览器的子集。
铺垫了这么多,就是为了帮助您回忆起技术发展的脉络和技术趋势,能够更好的理解下面即将要表达的文稿,下面咱们正式开始介绍 Flutter。
Flutter 能介绍的技术点其实很是多,这里找了一些具备表明性的技术项,结合本身的理解跟你们分享一下。包括设计思路、渲染方式、UI 的生命周期。由于这几个点,跟 React 技术栈风格很是类似,以这种思考结构去对比介绍,能够帮助你们更好的理解这项技术自己。
Google 了一下关键词,搜素获得了这张图片,从下向上进行一些描述:
Embedder:是操做系统适配层,实现了渲染 Surface 设置,线程设置,以及平台插件等平台相关特性的适配。从这里咱们能够看到,Flutter 平台相关特性并很少,这就使得从框架层面保持跨端一致性的成本相对较低。
Flutter Engine:这是一个纯 C++实现的 SDK,其中囊括了 Skia 引擎、Dart 运行时、文字排版引擎等。不过说白了,它就是 Dart 的一个运行时,它能够以 JIT、JIT Snapshot 或者 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 的时候,直接导入这个库便可使用组件等功能。
Framework 这一层是与开发者相关性最强的一层,逐一介绍一下,其中的模块:
Foundation:在最底层,主要定义底层工具类和方法,以提供给其余层使用。
Animation:是动画相关的类,能够基于此建立补间动画(Tween Animation)和物理原理动画(Physics-based Animation),相似 Android 的 ValueAnimator 和 iOS 的 Core Animation。
Painting:封装了 Flutter Engine 提供的绘制接口,例如绘制缩放图像、插值生成阴影、绘制盒模型边框等。
Gesture:提供处理手势识别和交互的功能
Rendering:是框架中的渲染库。控件的渲染主要包括三个阶段:布局(Layout)、绘制(Paint)、合成(Composite)。
PS:虽然很早知道 Flutter,但实际写 Flutter 时间也比较短暂。引擎源码层面,目前也没有深刻的涉猎。了解的方式能够经过本身阅读源码,或者找谷歌、阿里、美团、以及我司的开发者帮忙。从技术角度来了解这些,在须要的阶段,不会成为你们的瓶颈。毕竟商业世界充满了壁垒,而应用层面的技术自己是开放的。
简单描述一下 JIT 与 AOT:
JIT 在运行时即时编译,在开发周期中使用,能够动态下发和执行代码,开发测试效率高,但运行速度和执行性能则会由于运行时即时编译受到影响。
AOT 即提早编译,能够生成被直接执行的二进制代码,运行速度快、执行性能表现好,但每次执行前都须要提早编译,开发测试效率低。
Dart 是什么
它的目标在于成为下一代结构化 Web 开发语言。Dart 发布于 2011 年 10 月 Google 的 "GOTO 国际软件开发大会"。是一种基于类编程语言(class-based programming language),在全部浏览器都可以有高性能的运行效率。Chrome 浏览器内置了 Dart VM,能够直接高效的运行 dart 代码(2015 年被移出)。支持 Dart 代码转成 Javascript,直接在 Javascript 引擎上运行。dart2js(https://dart.dev/tools/dart2js)
Dart 的特色
开发时 JIT,提高开发效率;发布时 AOT,提高性能。不会面对 JS 与 Native 之间交互的问题了。Dart 的内存策略,采用多生代算法(与 Node 有一些相似)。线程模型依旧是单线程 Event Loop 模型,经过 isolate 进行隔离,能够下降开发难度(与 Node 也很是相似)。Dart 的生态,这个跟 Node.js 差距十分明显,npm 仍是行业中最活跃的。而静态语法与排版方式,纯前端入门仍是有必定成本。
备注:(1)TS 能够必定程度上帮助 JS 添加一些静态检测,但本质上依旧是没法达成这样的效果;(2) 关于入门成本这个问题,若是您想深刻,我相信这都不会成为问题。关键看是否能为业务和团队带来价值。
Flutter 选择 Dart 的缘由
健全的类型系统,同时支持静态类型检查和运行时类型检查。代码体积优化(Tree Shaking),编译时只保留运行时须要调用的代码(不容许反射这样的隐式引用),因此庞大的 Widgets 库不会形成发布体积过大。丰富的底层库,Dart 自身提供了很是多的库。多生代无锁垃圾回收器,专门为 UI 框架中常见的大量 Widgets 对象建立和销毁优化。跨平台,iOS 和 Android 共用一套代码。JIT & AOT 运行模式,支持开发时的快速迭代和正式发布后最大程度发挥硬件性能。Native Binding。在 Android 上,v8 的 Native Binding 能够很好地实现,可是 iOS 上的 JavaScriptCore 不能够,因此若是使用 JavaScript,Flutter 基础框架的代码模式就很难统一了。而 Dart 的 Native Binding 能够很好地经过 Dart Lib 实现。
Flutter 实现思路
看到了上面的介绍,这里总结一下 Flutter 的实现思路。它开辟了新的设计理念,实现了真正的跨平台的方案,自研 UI 框架,它的渲染引擎是 Skia 图形库来实现的,而开发语言选择了同时支持 JIT 和 AOT 的 Dart。不只保证了开发效率,同时也提高了执行效率。因为 Flutter 自绘 UI 的实现方式,所以也尽量的减小了不一样平台之间的差别。也保持和原生应用同样的高性能。所以,Flutter 也是跨平台开发方案中最灵活和完全的那个,它重写了底层渲染逻辑和上层开发语言的一整套完整解决方案。
完全跨端:
Flutter 构建了一整套包括底层渲染、顶层设计的全套开发套件。
这样不只能够保证视图渲染在 Android 和 IOS 上面的高度一致,也能够保证渲染和交互性能(媲美原生应用)。
与现有方案核心区别:
类 RN 方案,JS 开发,Native 渲染。数据通讯 bridge;
Hybird 浏览器渲染 + 原生组件绘制;
Flutter 设计自闭环,完成渲染和数据通讯;
谈到 UI 渲染方案,做为前端开发,咱们是绕不过如今如火如荼的三大框架的。为何要谈 类 React 方案呢?由于 Flutter 的设计方案,与 React 设计具备同样的思路。在渲染这里咱们会谈及 控件、渲染原理、以及生命周期。
Flutter 是如何进行页面渲染的呢?传统 Web 是经过浏览器,而 Flutter 是自绘。所谓自绘就是用户界面上 Flutter 本身绘制到界面,无需依赖 Ios 和 Android 原生能力,是经过一个叫作 Skia 引擎进行页面绘图。
Skia 是一个 2D 的绘图引擎库,其前身是一个向量绘图软件,Chrome 和 Android 均采用 Skia 做为绘图引擎。Skia 提供了很是友好的 API,而且在图形转换、文字渲染、位图渲染方面都提供了友好、高效的表现。Skia 是跨平台的,因此能够被嵌入到 Flutter 的 iOS SDK 中,而不用去研究 iOS 闭源的 Core Graphics / Core Animation。
Skia 是用 C++ 开发的、性能彪悍的 2D 图像绘制引擎,其前身是一个向量绘图软件。Skia 在图形转换、文字渲染、位图渲染方面都表现卓越,并提供了开发者友好的 API。Android 自带了 Skia,因此 Flutter Android SDK 要比 iOS SDK 小不少。正是得益于 Skia 的存在:
Flutter 底层的渲染能力获得了统一,不在须要使用作双端适配;
经过 OpenGL、GPU,不须要依赖原生的组件渲染框架。
Flutter 能够最大限度的抹平平台差别,提高渲染效率和性能。
用户能够看到一张图像展现,至少须要三类介质:CPU、GPU 和 显示器。CPU 负责图像的数据计算,GPU 负责图像数据的渲染,而显示器是最终图片展现的载体。CPU 拿到须要上屏的数据作处理和加工,处理完成以后交给 GPU,GPU 在渲染以后将数据放入帧缓冲区,随后随着控制同步信号 (VSync) 以周期性的频率,从缓冲区内读出数据,在显示器上进行图像呈现。并且操做系统就是一个无限循环的机制,不停的重复上面的操做,进行显示器的更新.
Flutter 的渲染总体流程也是这样的, Dart 进行视图数据的合成,而后交给 Skia 引擎进行处理,处理以后再交给 GPU 进行数据合成,而后准备上屏。当一帧图像绘制完毕后准备绘制下一帧时,显示器会发出一个垂直同步信号(VSync),因此 60Hz 的屏幕就会一秒内发出 60 次这样的信号。
如上图所示,Flutter 渲染流程分为 7 个步骤:
首先是获取到用户的操做,而后你的应用会所以显示一些动画
接着 Flutter 开始构建 Widget 对象。
Widget 对象构建完成后进入渲染阶段,这个阶段主要包括三步:
布局元素:决定页面元素在屏幕上的位置和大小;
绘制阶段:将页面元素绘制成它们应有的样式;
合成阶段:按照绘制规则将以前两个步骤的产物组合在一块儿
最后的光栅化由 Engine 层来完成。
布局
布局时 Flutter 深度优先遍历渲染对象树。数据流的传递方式是从上到下传递约束,从下到上传递大小。也就是说,父节点会将本身的约束传递给子节点,子节点根据接收到的约束来计算本身的大小,而后将本身的尺寸返回给父节点。整个过程当中,位置信息由父节点来控制,子节点并不关心本身所在的位置,而父节点也不关心子节点具体长什么样子。
为了防止因子节点发生变化而致使的整个控件树重绘,Flutter 加入了一个机制——Relayout Boundary,在一些特定的情形下 Relayout Boundary 会被自动建立,不须要开发者手动添加。
边界:Flutter 使用边界标记须要从新布局和从新绘制的节点部分,这样就能够避免其余节点被污染或者触发重建。就是控件大小不会影响其余控件时,就不必从新布局整个控件树。有了这个机制后,不管子树发生什么样的变化,处理范围都只在子树上。
缓存:要提高性能表现,缓存也是少不了的。在 Flutter 中,几乎全部的 Element 都会具备一个 key,这个 key 是惟一的。当子树重建后,只会刷新 key 不一样的部分。而节点数据的复用就是依靠 key 来从缓存中取得。
在肯定每一个空间的位置和大小以后,就进入绘制阶段。绘制节点的时候也是深度遍历绘制节点树,而后把不一样的 RenderObject 绘制到不一样的图层上。
绘制
在布局完成以后,渲染对象树中的每一个节点都有了明确的尺寸和位置。Flutter 会把全部的 Element 绘制到不一样的图层上。与布局过程相似,绘制的过程也是深度优先遍历,先绘制父节点,而后绘制子节点。如下图为例:节点 一、节点 二、节点 三、四、5,最好绘制节点 6。
如上图能够看到一种场景,就是好比视图可能会合并,致使 节点 2 的子节点 5 与 它的 兄弟节点 6 处于同一个图层,这样会致使当 节点 2 须要重绘的时候,与其无关的节点 6 也会被重绘,带来性能问题。
为了解决上面的问题,Flutter 提出了布局边界的机制 —— 重绘边界(Repaint-Boundary)。在重绘边界内,Flutter 会强制切换新的图层,这样能够避免边界内外的互相影响,避免无关内容虽然处于同一个层级致使的没必要要的重绘。
重绘边界的一个典型场景就是 ScrollView。ScorllView 滚动的时候会刷新视图,从而触发内容重绘,而当滚动内容重绘时,通常状况下其它内容是不须要被重绘的。这个时候重绘边界就很是有价值了。
这里思路就是更精细化的对组件的更新进行最小范围的控制。
合成和渲染
最上面已经展现了 Flutter 的 7 层渲染流水线(Rendering pipline)的图里。这里主要描述一下对合成和渲染的理解。渲染流水线是由垂直同步信号(Vsync)驱动的。这个概念很相似咱们平时说的 FPS 的概念,每秒 60 帧,太低的频率会显得页面很卡。
当每一次 Vsync 信号到来之后,Flutter 框架会按照图里的顺序执行一系列动做:
动画(Animate)、构建(Build)、布局(Layout)和绘制(Paint)
最终生成一个场景(Scene)以后送往底层,由 GPU 绘制到屏幕上。
Flutter App 只有在状态发生变化的时候须要触发渲染流水线。当你的 App 无任何状态改变的时候,Flutter 是不须要从新渲染页面的。因此,Vsync 信号须要 Flutter App 去调度。好比,咱们在 Widget 内使用了 setState 方法改变了控件的状态。
整个渲染流水线是运行在 UI 线程里的,以 Vsync 信号为驱动,在框架渲染完成以后会输出 Layer Tree。Layer Tree 被送入 Engine,Engine 会把 Layer Tree 调度到 GPU 线程,在 GPU 线程内合成(compsite)Layer Tree,而后由 Skia 2D 渲染引擎渲染后送入 GPU 显示。这里提到 Layer Tree 是由于咱们即将要分析的渲染流水线绘制阶段最终输出就是这样的 Layer Tree。因此绘制阶段并非简单的调用 Paint 函数这么简单了,而是不少地方都涉及到 Layer Tree 的管理。
Flutter 只关心向 GPU 提供视图数据,GPU 的 VSync 信号同步到 UI 线程,UI 线程使用 Dart 来构建抽象的视图结构,这份数据结构在 GPU 线程进行图层合成,视图数据提供给 Skia 引擎渲染为 GPU 数据,这些数据经过 OpenGL 或者 Vulkan 提供给 GPU。
这里描述一下合成的概念,所谓合成就是由于咱们绘制的页面结构复杂,若是直接交付给绘图引擎去进行图层渲染,可能会出现大量的渲染内容重绘,所以,须要先进性一次图层合成,就是说先把全部的图层根据大小、层级等规则计算出最终的显示效果,将相同的图层合并,简化渲染树,提高渲染效率。
Flutter 会将合成以后的数据,交给 Skia 进行页面二维图层的渲染。
Flutter 绘制界面的基础是 Widget,也就是描述页面的最小模块。
Flutter 的核心设计思想就是 "一切皆 Widget":
前端同窗能够把 Widget 理解为 Web Component 的 组件 便可。
一种结构化数据的抽象,包含了组件的布局、渲染属性、事件响应信息等。
在这一个部分咱们对比着 React 的设计方式对比着看一下 Flutter 的实现,在 React 中您能够看到三种很重要的名称。JSX、Virtual Dom、真实 Dom,而在 Flutter 中咱们依然能够看到对应的三类抽象的数据结构分别是 Widget、Element 和 RenderObject,他们的功能与 React 内三个数据抽象有殊途同归之处。
Widget 相似 React VM 的 F(x) = Y 中的 x 存在
Flutter 中的 Widget 是彻底不可变的!只要当视图发生变化,Flutter 就会从新建立一个新的 Widget 进行更新。便是 React 也是有必定的数据 Diff 的策略,而这里变动即建立的方式,会带来大量的销毁和重建的过程,是否很是消耗性能?
Widget 对标的是 标识 React 的虚拟 DOM 节点的 数据描述 JSX,不是真实渲染的页面 DOM。只是数据的抽象,不涉及视图渲染。而且 Widget 具备不可变性,也提高了 Widget 自己的复用性。所以并没大量的性能消耗,而 Dart 的做为静态语言的运行速度,也会有着超越 JS 的性能。
Element 是 Widget 的一个实例化对象
Element 承载了视图构建的上下文数据,是链接结构化的配置信息到完成最终渲染的桥梁;Element 是一个可变的数据结构, 能够大体理解为 Virtual DOM。能够进行 diff 更新;能够将真正须要修改的数据同步到 RenderObject 中。最大程度的下降渲染视图的修改,提高渲染效率。
RenderObject 负责视图渲染的对象
Flutter 的渲染分为 4 个部分。布局、绘制、合成、渲染,其中 布局和绘制是在 RenderObject 中完成的。Flutter 采用深度优的方式渲染对象树,肯定树中的各个对象的位置和尺寸,并把它绘制到不一样图层, 绘制完成以后交给 Skia 在 VSync 信号同步时从渲染树合成位图,而后交给 CPU 进而完成上屏。
Widget 一样分为有状态 和 无状态组件
无状态控件 StatelessWidget 相似 React 的 PFC。有状态控件 StatefulWidget 就是 React 的 组件。如同 react 组件同样,使用有状态组件是有成本的。正确的评估你的需求,避免使用无心义的有状态组件。
这里比较大的区别,是 Flutter 直接把 Widget 设计成为了一个不可变的! 这也致使了技术方案的实现上存在了差别。
每当您看到组件、状态、视图这些名词的时候,伴随着它们的存在,必定会存在一个叫生命周期的概念。是的 ,Flutter 也存在它的生命周期。
建立
构造函数 --> initState --> didChangeDependencies --> build
State:构造方法是生命周期的起点,Flutter 会经过 StatefulWidget.createState 来建立一个 State。咱们能够经过初始化方法,接收父 Widget 传递过来的初始化 UI 配置参数,这些配置参数决定了 Widget 的最初配置效果
initState:会在 State 对象被插入视图树的时候调用,这个函数在 State 的生命周期中只会被调用一次,因此咱们能够在这里作一些初始化工做,好比为状态变量设定默认值。
didChangeDependencies:则用来专门处理 State 对象依赖关系变化,会在 initSate()调用结束后被 Flutter 调用。
build:做用是构建视图。经过以上步骤,Framework 认为 Sate 已经准备好了,因而调用 build。咱们须要在这个函数中,根据父 Widget 传递过来的初始化配置数据,以及 State 的当前状态,建立一个 Widget,而后返回。
更新
Widget 的状态更新,主要由三个方法触发:setState、didChangeDependencies 和 didUpdateWidget。
setState:是 咱们最熟悉的方式,控件内更新,而后从新 build。
didChangeDependencies:State 对象的依赖关系发生变化时,Flutter 会回调这个方法,随后触发组件构建。哪些状况下 State 对象的依赖关系会发生变化呢?典型场景是,系统语言 Locale 或者应用主题改变时,系统会通知 Sate 执行 didChangeDependencies 回调方法。
didUpdateWidget:当 Widget 的配置发生变化时,好比,父 Widget 触发重建(即父 Widget 的状态发生变化)时,热重载时,系统会调用这个函数。
一旦这三个函数被调用,Flutter 随后就会销毁老 Widget,并调用 build 方法重建 Widget。
销毁
组件的销毁相对比较简单。好比组件被移除,或是页面销毁的时候,系统会调用 diactivate 和 dispose 这两个方法,来移除或销毁组件。
当组件的可见状态发生变化时,deactivate 函数会被调用,这时 Sate 会被暂时从视图树中移除。值得注意的是,页面切换时,因为 State 对象在视图树中的位置发生了变化,须要暂时移除后再从新添加,从新触发组件构建,所以这个函数也会被调用。
当 State 对象被永久地从视图树中移除时,Flutter 会调用 dispose 函数。而一旦到这个阶段,组件就要被销毁了,因此咱们能够在这里进行最终的资源释放、移除监听、清理环境。
从后台切入前台,控制台打印的 App 生命周期变化以下:
AppLifecycleState.paused->AppLifecycleState.inactive->AppLifecycleState.resumed;
从前台退到后台,控制台打印的 App 生命周期变化以下:
AppLifecycleState.resumed->AppLifecycleState.inactive->AppLifecycleState.paused;
更详细的生命周期详解,您能够 Google 搜索 Flutter 生命周期 ,Github 上美团的工程师也有一个例子(https://github.com/cyndibaby905/11_Flutter_lifecycle)
粗略了整理了一下体验学习过程当中关于 Flutter 基本的部分,这上面大部分分支已经经过代码体验和实践过了。这里就不在一一的介绍了。这里找了三个实例,跟您分享,您能够 clone 下来,跟细节的体验一下:
布局案例:https://github.com/yang7229693/flutter-study
代码实例:https://github.com/nisrulz/flutter-examples
FlutterDemo: https://github.com/OpenFlutter/Flutter-Notebook
除了我上面列出的这些,还有不少要作,好比 运维、调试、自动化测试、兼容性、客户端 SDK 封装、国际化等等。固然对于开发者来讲,工程化、调试体验、组件化都是很是重要的。
这里我转换的代码是咱们的 APP 里面的业务代码。详细的操做流程(https://github.com/flutter/flutter_web/blob/master/OLD_README.md) Flutter 官方文档具备很好的说明。若是单纯转一个彻底不依赖 APP 的工程,估计您安装完环境就可使用了。转换商业产品的代码,仍是要处理一些奇奇怪怪的问题,相信这对您都不会是问题。您能够在这里 安装和环境配置 进行环境配置。Flutter 官网提供了一个 案例 您能够尝试一下。官方给了一个开箱即学的 开发文档 。
上面的视频里面展现咱们 企鹅辅导 的第三个 TAB 内的 Flutter 业务,以及转换后的 Web 页面。能够明显看到,有一局部确实有些失真,可是彻底可用。这里页面渲染有一部分 Canvas 渲染 和 DOM 填充 进行的页面展现。Dart 当年自然支持在 Chrome 中使用,而且长期以来一直支持转换为 JavaScript。所以,能够碰见的将来,随着 Flutter 的发展,Dart To Js 业务实践的进化速度,可能会超过 WASM 的使用。
这里须要解决一些问题,整理了一下官方建议和实践的体验:
首先还不建议,在产品化中使用,但既然已经合入 Master,相信这一天也不会远了。
业务使用的时候,须要把系统依赖解决掉,好比:本地存储、网络请求这些。如客户端使用的是 WNS,而前端须要使用的是 HTTPS。对 3D 动画依赖比较严重的业务,短时间就不要选择 Flutter 做为业务选选了。Flutter to Web 将来做为业务容灾的策略仍是能够的。
Flutter 官网(https://flutter.dev)
Flutter 中文网(https://flutterchina.club)
Flutter 实战(https://book.flutterchina.club)
闲鱼技术博文(https://www.yuque.com/xytech/flutter)
这里再次感谢前人的沉淀,确实要学习的东西太多了,实际想要写的文章,远比这里面描述要多不少,可是因为时间成本太高,不得不砍掉了很是多的内容。后面随着对 Flutter 更深刻的了解,有机会再跟您更详细的分享 Flutter 的内部设计原理。我只是知识的搬运工,在应用层领域做为开发,最大的价值就是服务好产品,最大限度的用技术知足产品诉求。至于核心的底层开发建设,人生能作到什么程度,要看缘分;可是最大限度的服务好业务,只要有责任心就能够了。
在此,也特别感谢领导的鼓励,去尝试体验 Flutter 这项技术。了解和认知只是一个开始,后面若是有机会,也能够作一些业务尝试。在行业内部阿里的闲鱼作的仍是很是深刻,美团的小伙伴也有深度的尝试,感谢他们对行业的贡献。
固然,我更但愿您是前端,而且也对 Flutter 实践有着兴趣,可是又缺乏落地的项目,您也能够联系咱们,团队能够给您提供一个靶场,进行业务实践的落地。光说不练都是假把式,核心仍是要用业务去砸!