This commit is contained in:
guoshuyu 2023-08-01 14:29:08 +08:00
parent a0c182869a
commit 05c3ae0b01
8 changed files with 617 additions and 1 deletions

View File

@ -82,6 +82,10 @@
* [Flutter 3.10 适配之单例 Window 弃用,一起来了解 View.of 和 PlatformDispatcher](Flutter-310Win.md)
* [Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel ](Flutter-N25.md)
* [Flutter 小技巧之 InkWell & Ink 你了解多少](Flutter-N26.md)
* [Flutter 小技巧之滑动控件即将“抛弃” shrinkWrap 属性](Flutter-N28.md)
* [Flutter III 之你不知道的 PlatformView 的混乱之治](Flutter-N30.md)
* [掘力计划Flutter 混合开发的混乱之治【直播回顾】](Flutter-JL2023.md)
* [社区说|Flutter 一知半解,带你拨云见月](Flutter-SQS2023.md)

View File

@ -176,4 +176,4 @@ Flutter 的 Visual Studio Code 扩展也获得了许多增强功能,包括**
- Web 上的原始图像使用正确的来源和颜色https://docs.flutter.dev/release/breaking-changes/raw-images-on-web-uses-correct-origin-and-colors
- Scribble Text Input Clienthttps://docs.flutter.dev/release/breaking-changes/scribble-text-input-client
如果你仍在使用这些 API可以[阅读 flutter.dev 上的迁移指南](https://docs.flutter.dev/release/breaking-changes),与往常一样,非常感谢社区[提供的测试](https://github.com/flutter/tests/blob/master/README.md),帮助我们识别这些重大变化。
如果你仍在使用这些 API可以[阅读 flutter.dev 上的迁移指南](https://docs.flutter.dev/release/breaking-changes),与往常一样,非常感谢社区[提供的测试](https://github.com/flutter/tests/blob/master/README.md),帮助我们识别这些重大变化。FL

194
Flutter-JL2023.md Normal file
View File

@ -0,0 +1,194 @@
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image1.png)
# 掘力计划Flutter 混合开发的混乱之治【直播回顾】
Hello大家好我是 Flutter GDE 郭树煜,今天的主题是 Flutter 的混合开发,但是其实内容并不会很广,主要分享会集中在 Android 平台的 `PlatformView ` 实现上,其实本次内容之前我已经在掘金发过一篇[简要的文字概括](https://juejin.cn/post/7257119213889454139),今天主要是根据这个内容做一个更详细的技术展开。
> 之所以会集中在 Android 平台的 `PlatformView ` 实现上去分享是因为正如标题所示那样Android 平台的 `PlatformView ` 实现目前呈现的状态:混乱。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image2.png)
## 混乱之始
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image3.png)
就像每个混乱都有它的起源,比如艾泽拉斯的混乱之治起源于燃烧军团的入侵,而混合开发在 Flutter 领域之所以混乱,主要源自它本身独特的实现。
我们常说光明总是伴随着黑暗Flutter 最大的特点在于:渲染的控件是通过 Skia 直接和 GPU 交互,所以可做到在性能不错的同时,在不同平台得到一致性的渲染效果。
也就是说 Flutter 控件和平台无关,甚至连 UI 绘制线程都和原生平台 UI 线程是相互独立,这就决定了: **Flutter 在和原生平台做混合开发时会有相对高昂的技术成本**
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image4.png)
> 简单想象下,例如你需要把一个原生的按键渲染到 WebView 里面和前端标签混合到一起,这是不是很不可思议?
还一个更容易理解的角度,其实从渲染的角度看 Flutter 更像是一个「游戏」引擎,只是他可以用来开发 App ,当然它现在也可以用来开发游戏,近两年谷歌的 I/O 大会都用它做了热场游戏,例如今年就做了一个像图片里的卡牌动作游戏,所以 Flutter 其实更像是游戏引擎的逻辑,所以它独立于平台的特性,既是优势,也带来了劣势:
> 毕竟把原生控件渲染进一个类似 unity 的引擎进行混合并不容易。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image5.gif)
那如果只是单纯的技术问题,也只是实现成本较高而已,为什么会说混乱呢?这就需要谈到目前 Android `PlatformView` 的实现。
不过再谈及 Android `PlatformView ` 实现之前,先简单说说 iOS iOS 平台是**通过将 Flutter UI 分为两个透明纹理来完成组合**
> 需要在 `PlatformView` 下方呈现的 Flutter UI 可以被绘制到其下方的纹理;而需要在 `PlatformView` 上方呈现的 Flutter UI 可以被绘制到其上方的纹理, 它们只需要在最后组合起来就可以了。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image6.png)
简单来说,就是通过在 `NativeView` 的不同层级设置不同的透明图层,然后把不同位置的控件渲染到不同图层,最终达到组合起来的效果。
> 那 Android 是否采用这种实现?答案明显并不是,因为这种实现在 iOS 上框架渲染后系统会有回调通知,例如:*当 iOS 视图向下移动 `2px` 时,我们也可以将其列表中的所有其他 Flutter 控件也向下渲染 `2px`*。
但是在 Android 上就没有任何有关的系统 API因此无法实现同步输出的渲染所以基于此在各个版本的更新迭代下 Android 的 `PlatformView ` 实现衍生出多种实现逻辑。
目前活跃在 Android 平台的 `PlatformView` 支持主要有以下三种:
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image7.png)
可以看到官方都已经为大家定义好了简称 VD、HC、TLHC ,有了简称也方便大家提 issue 时沟通,毕竟每次在讨论时都用全称很费劲:
> **因为你需要不停指出你用的是什么模式然后在什么模式下正常or不正常另外知道这些简称最大的作用就是看 issue 时不迷糊**
所以后续我们也会用简称来称呼它们,而之所以会有这么多模式,其实就是因为**没有一种模式可以完全满足和覆盖需求** ,这也导致了明明后来出现的模式是为了替代旧的支持,但是最终形成了共存的情况,从而导致了后续混乱的开始。
> 这就好比兽族入侵艾泽拉斯,最后的结果却是兽族和人族共存下来,各个模式之间最终既相爱又相杀的一种情况。
## VD
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image8.png)
我们先说最早的 VDVD 简单来说就是使用 VirtualDisplay 渲染原生控件到内存。
`VirtualDisplay` 类似于一个虚拟显示区域,需要结合 `DisplayManager` 一起调用,`VirtualDisplay` 一般在副屏显示或者录屏场景下会用到,而在 Flutter 里 `VirtualDisplay` 会将虚拟显示区域的内容渲染在一个内存 `Surface`上。
在 Flutter 中需要用到 Android 原生 View 的地方会让你使用一个叫 `AndroidView` 的控件,如图所示,**在 Flutter 中通过将 `AndroidView` 需要渲染的内容绘制到 `VirtualDisplays` 中 ,然后通过 textureId 在 `VirtualDisplay` 对应的内存中提取绘制的纹理**
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image9.png)
> 通过在 Dart 层提供一个 `AndroidView` ,从而获取到控件所需的大小,位置等参数,然后通过 `textureId` ,主要是这个 id 提交给 Flutter Engine ,通过 id Flutter 就可以在渲染时将画面从内存里提出出来。
那么这个实现在满足和最初混合开发接入原生控件的同时,也带来和许多的局限,最常见的就是**触摸事件**和**文字输入**的支持问题。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image10.png)
#### 触摸事件
因为控件是被渲染在内存里,所以虽然**你在 UI 上看到它就在那里,但是事实上它并不在那里**,你点击到的是 Flutter 所在的原生 `FlutterView`**用户产生的触摸事件是直接发送到 `FlutterView`**。
> 触摸事件需要在 `FlutterView` 到 Dart ,再从 Dart 转发到原生,然后如果原生不处理又要转发回 Flutter ,中间如果还存在其他派生视图,事件就很容易出现丢失和无法响应。
而 Android 的 `MotionEvent` 在转化到 Flutter 过程中可能会因为机制的不同,存在某些信息没办法完整转化的丢失。
#### 文字输入
另外关于文字输入 的问题,一般情况下 **`AndroidView` 是无法获取到文本输入,因为 `VirtualDisplay` 所在的内存位置会始终被认为是 `unfocused` 的状态**。
> 而 `InputConnections``unfocused` 的 View 中通常是会被丢弃。
所以 **Flutter 重写了 View 的 `checkInputConnectionProxy` 方法,这样 Android 会认为 `FlutterView` 是作为 `AndroidView` 和输入法编辑器IME的代理**,这样 Android 就可以从 `FlutterView` 中获取到 `InputConnections` 然后作用于 `AndroidView` 上面。
> 在 Android Q 开始又因为非全局的 `InputMethodManager` 需要新的兼容
所以键盘问题在第一代 VD 上最为突出,因为在不同版本的 Android 上可能会经常非常容易异常,为 `WebView` 作为混合开发里最常用到的插件,键盘是它最精彩会用到的能力之一,这个局限对于 VD 来说非常致命。
## HC
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image11.png)
Flutter 是在 1.2 版本开始支持 HC简单说就是直接把原生控件覆盖在 Flutter 上进行堆叠,它使用了类似 iOS 的实现思路,简单来说就是 `HybridComposition` 模式会直接把原生控件通过 `addView` 添加到 `FlutterView` 上 。
举一个简单的例子,如图所示,一个原生的 `TextView` 被通过 HC 模式接入到 Flutter 里(`NativeView`),而在 Android 的显示布局边界和 Layout Inspector 上可以清晰看到: **灰色 `TextView` 通过 `FlutterMutatorView` 被添加到 `FlutterView` 上被直接显示出来**
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image12.png)
**所以在 HC 模式里 `TextView` 是直接在原生代码上被 add 到 `FlutterView` 上,而不是提取纹理**。
那如果我们看一个复杂一点的案例,如图所示,其中蓝色的文本是原生的 `TextView` ,红色的文本是 Flutter 的 `Text` 控件,在中间 Layout Inspector 的 3D 图层下可以清晰看到:
- 两个蓝色的 `TextView` 是被添加在 `FlutterView` 之上,并且把没有背景色的红色 RE 遮挡住了
- 最顶部有背景色的红色 RE 也是 Flutter 控件,但是因为它需要渲染到 `TextView` 之上,所以这时候多一个 `FlutterImageView` ,它用于承载需要显示在 Native 控件之上的纹理,从而达 Flutter 控件“真正”和原生控件混合堆叠的效果。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image13.png)
**可以看到 `Hybrid Composition` 上这种实现,能更原汁原味地保流下原生控件的事件和特性,因为从原生角度看它就是原生层面的物理堆叠,需要叠加一个层级就多加一个 `FlutterImageView` ,同一个层级的 Flutter 控件共享一个 `FlutterImageView`** 。
当然,这里出现的 `FlutterImageView` ,其实还有一个作用,就是**为了解决动画同步和渲染**。
前面说过HC 是直接被添加到原生 `FlutterView` 上面,所以走的还是原生的渲染流程和时机,而这时候通过 `FlutterImageView` ,也就是把 Flutter 控件渲染也同步到原生的 `OnDraw` 上,这样对于画面同步会更好。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image14.png)
当然,这样带来了一个问题,因为此时原生控件是直接渲染,所以需要在原生的平台线程上执行,纯在 Flutter 的 UI 线程就存在线程同步问题,所以在此之前一些场景下会有画面闪烁 bug ,例如:
- `A page` -> `webview page` -> `B page` `webview page` 打开 `B page` 时,有时候 `A page` 的 UI 在 `B page ` 突然闪动
- 当 `B page` 返回 `webview page `, 然后再返回 `A page` 有时候 `B page` UI 突然闪现在 `A page`
虽然这个问题最后也通过类似线程同步实现解决,但是也带来一定程度的性能开销,另外在 Android 10 之前还会存在 GPU->CPU->GPU的性能损耗所以 HC 属于会性能开销较大,又需要原生控件特性的场景。
## TLHC
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image15.png)
3.0 版本之后开始支持 TLHC 模式,最初它的目的还是取代上面这两种模式,解决混乱之治,但是奈何它最后和阿尔萨斯一样,成了新一代的巫妖王。
目前 TLHC 和 VD 还有 HC 一起共存下来,该模式的最大特点是控件虽然在还是布局在该有的位置上,但是其实是通过一个 `FrameLayout` 代理 `onDraw` 然后替换掉 child 原生控件的 `Canvas` 来实现混合绘制。
TLHC 算是参考了 VD 和 HC 的模式,然后利用平台的特点来完成渲染,所以它带了 HC ,但又并不是 HC最大的特点就是它不在让控件通过原生线程绘制所以也就不需要做线程同步。
而说它参考 VD ,主要是它和 VD 很类似,不同之处在于**原生控件纹理的提取方式上**,如图可以看到
- 从 VD 到 TLHC 里, **Plugin 的实现是可以无缝切换,因为主要修改的地方在于底层对于纹理的提取和渲染逻辑**
- 以前 Flutter 中将 `AndroidView` 需要渲染的内容绘制到 `VirtualDisplays` ,然后在 `VirtualDisplay` 对应的内存中,绘制的画面就可以通过其 `Surface` 获取得到;**现在 `AndroidView` 需要的内容,会通过 View 的 `draw` 方法被绘制到 `SurfaceTexture` 里,然后同样通过 `TextureId` 获取绘制在内存的纹理**
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image16.png)
简单说就是不需要绘制到副屏里,现在直接通过 override `View``onDraw` 方法就可以了,然后因为它是绘制到内存,最终渲染还是在 Flutter 线程完成,所以也就不需要线程同步。
举个例子,还是之前的代码,如图所示,这时候通过 TLHC 模式运行之后,通过 Layout Inspector 的 3D 图层可以看到,两个原生的 `TextView` 通过 `PlatformViewWrapper` 被添加到 `FlutterView` 上。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image17.png)
但是不同的是,**在 3D 图层里看不到 `TextView` 的内容,因为绘制 `TextView` 的 Canvas 被替换了**,所以 `TextView` 的内容被绘制到内存的 Surface 上,最终会在渲染时同步 Flutter Engine 里。
> 不过 **`PlatfromViewWrapper` 拦截了 Event ,但是其实还是通过 Dart 做二次分发响应,从而实现不同的事件响应** ,它和 VD 的不同是, VD 的事件响应都是在 `FlutterView`但是TLHC 模式,是有独立的原生 `PlatfromViewWrapper` 控件来开始,所以区域效果和一致性会更好。
**那么为什么说 TLHC 模式是巫妖王呢**
因为这种实现天然不支持 `SurfaceView` ,因为 `SurfaceView` 是双缓冲机制,所以通过 parent 替换 `Canvas` 的实现并不支持,也就是对于类似地图、视频等插件,如果是 `SurfaceView` ,会出现无法支持的问题。
那有人说,我用 `TextureView` 不就行了?对不起,目前在 [#103686](https://github.com/flutter/flutter/issues/103686) 下,对于 `TextureView` 有时候也会出现不正常更新的异常情况。
所以 TLHC 没能带来终结,它反而引入的新的致命缺陷,并且和 VD 还有 HC 融合到了一起。
## 混乱之治
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image18.png)
那为什么这三种模式会导致混乱?首先我们简单总结下前面介绍的内容:
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image19.png)
而随着三种模式的存在,在 API 层面,目前出现了兼容式运行的情况,在 API 上,在目前 3.0+ 的 Flutter 上同样对应有三个 API ,但是这三个 API 并不是直接对应上述三种模式:
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image20.png)
看到没有,这里有一个问题就是:**你其实没办法主动控制是 TLHC 还是 VD ,对于 HC 你倒是可以强行指定**。
另外,不知道你注意到没有,不管是 `initAndroidView` 还是 `initSurfaceAndroidView` ,它们都可能会在升级到新版本时使用 TLHC 模式,**也就是如果你的 Plugin 没有针对性做更新,那么可能会在不知觉的情况下换了模式,从而有可能出现 bug** 。
> 对于 TLHC 还有一个问题,就是如果你原本没有 SurfaceView ,但是后面添加 SurfaceView ,也会触发异常显示的问题。
现在你看出 PlatformView 的混乱了吧?从底层实现的不统一,到 API 再不同版本下不同的行为变化,这就是目前 Android 在 PlatformView 支持下的混乱生态,同时如果你对于目前 PlatformView 存在的问题感兴趣,可以查阅以下相关 issue
- [#103686](https://github.com/flutter/flutter/issues/103686)
- [#109690](https://github.com/flutter/flutter/issues/109690)
- [#112712](https://github.com/flutter/flutter/issues/112712)
- [#130692](https://github.com/flutter/flutter/issues/130692)
不过整体来说,官方还是建议大家使用 TLHC 模式,因为它的思路总的来说性能会更好,并且更符合预期,在不出现兼容运行的情况下。
好了,今天分享的内容就这些,谢谢大家。
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image21.png)

80
Flutter-N28.md Normal file
View File

@ -0,0 +1,80 @@
# Flutter 小技巧之滑动控件即将“抛弃” shrinkWrap 属性
相信对于 Flutter 开发的大家来说, ListView 的 `shrinkWrap` 配置都不会陌生,如下图所示,每当遇到类似的 `unbounded error ` 的时候,总会有第一反应就是给 `ListView` 加上 `shrinkWrap: true` 就可以解决问题,那为什么现在会说 `shrinkWrap` 即将被“抛弃”呢?
![](http://img.cdn.guoshuyu.cn/20230718_N28/image1.png)
其实说完全“抛弃”也不大严谨,从目前官方的规划来看, `shrinkWrap` 配置将从滑动控件里弃用,因为团队觉得**现阶段的开发人员大多数时候不知道它的实际含义,只是单纯使用它解决问题,在使用过程中容易出现错误的性能损耗而不自知**。
![](http://img.cdn.guoshuyu.cn/20230718_N28/image2.png)
当然,这个提议并不是说完全废除 `shrinkWrap` 的支持,而且类似通过全新的 `Widget` 来替代,用更形象的命名,例如 `NonLazyListView` 等。
![](http://img.cdn.guoshuyu.cn/20230718_N28/image3.png)
> **目前这个提议的等级是 P1 ,所以如果不意外的话,它的推进会很快**
那么 `shrinkWrap` 为什么会带来性能问题?它常用在什么场景?为什么会需要被提高到 P1 来进行调整?
首先我们需要简单理解 Flutter 滑动列表的实现和 `shrinkWrap` 的作用,在[《带你了解 Flutter 中的滑动列表实现》](https://juejin.cn/post/6956215495440007175)里我们介绍过,**Flutter 里的滑动列表是由 *`Viewport`* 、*`Scrollable`* 和相应的 *`Sliver`* 三部分组成**。
`ListView` 为例,如下图所示是 `ListView` 滑动过程的变化,其中:
- 绿色的 `Viewport` 就是我们看到的列表窗口大小;
- 紫色部分就是处理手势的 `Scrollable`,让黄色部分 `SliverList``Viewport` 里产生滑动;
- 黄色的部分就是 `SliverList` 当我们滑动时其实就是它在 `Viewport` 里的位置发生了变化;
![](http://img.cdn.guoshuyu.cn/20230718_N28/image4.png)
所以 `ListView` 之所以可以“无限”滑动,就是因为首先有一个固定大小「窗口」, 只有在进入和靠近「窗口」的 Item 才会被布局渲染,从而保证了列表的性能。
但是这也带来了一个问题,如下图 1 的代码所示,它就因为 ` Column` 的特性,没办法直接计算得到 `Viewport` 的大小,所以会抛出错误。
| ![](http://img.cdn.guoshuyu.cn/20230718_N28/image5.png) | ![](http://img.cdn.guoshuyu.cn/20230718_N28/image6.png) | ![](http://img.cdn.guoshuyu.cn/20230718_N28/image7.png) |
| ------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- |
有时候我们会如上图 2 所示,通过给 `ListView` 加一个 `Expanded` 来解决,这样 `ListView` 会充满 ` Column` 的剩余空间,从而得到一个固定的 `Viewport` 大小。
但是当我们希望此时 `ListView` 不充满,还可以居中显示的时候,就会采用如上图 3 所示那样,添加一个 `shrinkWrap: true`
> 虽然这个例子没有意义,但是它展示了 `shrinkWrap` 的“主要”场景,**另外 `shrinkWrap` 也常被用于 `ListView` 嵌套 `ListView` 这种不规范使用的场景中**。
`shrinkWrap` 的实现原理是什么?简单来说,现阶段 `shrinkWrap:true` 的时候,在滑动控件内部会采用一个特殊的 `ShrinkWrappingViewport` 「窗口」进行实现。
![](http://img.cdn.guoshuyu.cn/20230718_N28/image8.png)
`ShrinkWrappingViewport``Viewport` 的不同之处在于
- `Viewport` 是填充满主轴方向的大小
- `ShrinkWrappingViewport` 是调整自身大小去匹配主轴方向中 Item 的大小,而这种“收缩”的行为成本会变高,因为窗口大小需要通过 child 去“确定”。
例如,如下图所示,在 `ListView` 里,我们将 ` itemCount` 修改为 400 ,然后打印每个 Item 的 build ,由于 `shrinkWrap` 的作用,可以看到 400 个 child 都被输出。
![](http://img.cdn.guoshuyu.cn/20230718_N28/image9.png)
同样,在 Inspector 的 Widget Tree 里可以看到 400 个 child 都构建完成,尽管他们还远没有在 `ViewPort` 展示出来,所以 `shrinkWrap``ListView` 失去了懒加载的作用。
相反,如下图代码所示,如果去掉 `shrinkWrap` ,在 `Expand` 的作用下 ` ListView` 有了固定大小的 `ViewPort` ,此时就算是 ` itemCount` 是 400 ,但是也只会根据 `ViewPort` 构建所需的 19 个 child 。
![](http://img.cdn.guoshuyu.cn/20230718_N28/image10.png)
就算是因为滑动产生变化,正常情况下的 `ListView` 也保持着「固定」的长度,例如滑动到 160 的 index 的时候,此时开始的 `ListTitle` 的 index 是 135 ,而不会像 `shrinkWrap` 一样保持着全员 child 的构建。
![](http://img.cdn.guoshuyu.cn/20230718_N28/image11.png)
如何要深究的话,**其中关键点之一就在于 `updateOutOfBandData` 方法实现的不同**,在普通 `Viewport` 里, `updateOutOfBandData` 方法只是用于计算 `maxScrollExtent ` ,而如下图 1 所示,`ShrinkWrappingViewport` 里会对每个 child 的 `maxPaintExtent` 进行累计。
| ![](http://img.cdn.guoshuyu.cn/20230718_N28/image12.png) | ![](http://img.cdn.guoshuyu.cn/20230718_N28/image13.png) |
| -------------------------------------------------------- | -------------------------------------------------------- |
累计之后的得到的 `_shrinkWrapExtent` 最终会转化为 `ShrinkWrappingViewport` 自己的 `size` ,这也是 `ShrinkWrappingViewport` 为什么可以根据 child 调整「窗口」大小的原因。
所以,在此之前可能**开发者经常通过简单的 `shrinkWrap` 来解决问题,而比较少思考 `shrinkWrap` 的实现原理,或者说缺乏理解它的作用,从而带来了一些隐形的性能问题而不自知**,所以这也是为什么这次会有该调整的原因:
> 将 `shrinkWrap` 迁移到全新控件可以更直观让大家理解其作用,而其实大部分使用 `shrinkWrap` 的场景可以被其他实现替代。
- 例如前面提到的 `ListView` 嵌套 `ListView` 的场景,与其对通过配置 `shrinkWrap` 来实现,不如通过 `CustomScrollView` 结合不同 `SliverList` 或者其他 `Sliver` 组建完成组合。
- 而如果 child 并不多,其实也可以直接通过 `SingleChildScrollView` + `Column` 来实现,它在一定程度上效果和 `shrinkWrap` 类似。
所以,到这里你应该知道了 `shrinkWrap` 的实现逻辑和作用,其实本次主要也是想通过这个 new feature 变动,带大家重新认识下 `shrinkWrap` **因为接下来,它就不再叫 `shrinkWrap` 了,或者你以后也应该很少用到它**。

112
Flutter-N30.md Normal file
View File

@ -0,0 +1,112 @@
![](http://img.cdn.guoshuyu.cn/20230719_N30/image1.png)
# Flutter III 之你不知道的 PlatformView 的混乱之治
如果你是从 2018 年开始使用 Flutter ,那么相信你对于 Flutter 在混合开发的支持历程应该会有一个深刻的体会,如果你没尽力过这个时期,不要担心,通过我过往 `PlatformView` 的相关文章,你也可以有一个清晰的感受:
- [Flutter 3.0下的混合开发演进](https://juejin.cn/post/7113655154347343909)
- [告别 VirtualDisplay ,拥抱 TextureLayer](https://juejin.cn/post/7098275267818291236)
- [Flutter 深入探索混合开发的技术演进](https://juejin.cn/post/7093858055439253534)
- [HybridComposition 和 VirtualDisplay 的实现与未来演进](https://juejin.cn/post/7071549421116194847)
- [ Hybrid Composition 深度解析](https://juejin.cn/post/6858473695939084295)
- [Android PlatformView 和键盘问题](https://juejin.cn/post/6844904070906380296)
总而言之,目前 Flutter 对于 `PlatformView` 的支持,特别是在 Android 平台上,只能用一个字来形容:「乱」。
![](http://img.cdn.guoshuyu.cn/20230719_N30/image2.png)
这个「乱」不只是体现在 API 和底层实现方案上,更表现在你遇到 issue 时,不确定到底是因为什么引起的困惑上,因为目前 Flutter 在 Android 平台的 `PlatformView` 会根据不同的 SDK 版本和场景进行「兜底」兼容,存在各种历史包袱。
> 其实我已经不是很想写这方面的内容了,但是奈何总有人问,那么本篇就来个总结式科普。
目前活跃在 Android 平台的 `PlatformView` 支持主要有以下三种:
- Virtual Display (VD)
- Hybrid Composition (HC)
- Texture Layer Hybrid Composition (TLHC)
可以看到官方都已经为大家定义好了简称 VD、HC、TLHC ,有了简称也方便大家提 issue 时沟通,毕竟每次在讨论时都用全称很费劲:
> **因为你需要不停指出你用的是什么模式然后在什么模式下正常or不正常另外知道这些简称最大的作用就是看 issue 时不迷糊**
那么,接下来主要简单介绍它们的区别:
## VD
VD简单来说就是使用 VirtualDisplay 渲染原生控件到内存,然后利用 id 在 Flutter 界面上占用一个相应大小的位置,最后通过 id 关联到 Flutter Texture 里进行渲染。
![](http://img.cdn.guoshuyu.cn/20230719_N30/image3.png)
问题也很明显,因为控件不会真实存在渲染的位置,所以此时的点击和对原生控件的操作,其实都是需要由 Flutter 这个 View 进行二次转发,另外因为控件是渲染在内存里,所以和键盘交互需要通过二级代理处理,这就产生了各种键盘输入的异常问题。
> 键盘问题突出在不同版本的 Android 兼容上。
## HC
1.2 版本开始支持 HC简单说就是直接把原生控件覆盖在 Flutter 上进行堆叠,如果出现 Flutter Widget 需要渲染在 Native Widget 上,就采用新的 `FlutterImageView` 来承载新图层。
![](http://img.cdn.guoshuyu.cn/20230719_N30/image4.png)
好处是原生视图是直接显示渲染,坏处就是在 Android 10 之前存在 GPU->CPU->GPU的性能损耗。
另外因为此时原生控件是直接渲染,所以需要在原生的平台线程上执行,这和 Flutter 的 UI 线程就存在线程同步问题,所以在此之前一些场景下会有画面闪烁 bug 。
## TLHC
3.0 版本开始支持 TLHC 模式,最初的目的是取代上面这两种模式,奈何最终只能共存下来,该模式下控件虽然在还是布局在该有的位置上,但是其实是通过一个 `FrameLayout` 代理 `onDraw` 然后替换掉 child 原生控件的 `Canvas` 来实现混合绘制。
![](http://img.cdn.guoshuyu.cn/20230719_N30/image5.png)
> 所以看到此时上图 `TextView` 里没有了内容,因为 `TextView` 里的 `Canvas` 被替换成 Flutter 在内存里创建的 `Canvas`
但是这种实现天然不支持 `SurfaceView` ,因为 `SurfaceView` 是双缓冲机制,所以通过 parent 替换 `Canvas` 的实现并不支持。
## 总结
上述就是这目前三种模式的简单描述和对比,如果看不明白,可以通过前面的历史文章进行了解,总结下以下它们的主要问题:
- VD 控件不是被真实渲染,容易有触摸和键盘等问题
- HC 直接堆叠控件,会有性能开销和线程同步问题,某些场景容易出现闪烁和卡顿
- TLHC不支持 `SurfaceView` ,对于使用 `SurfaceView` 的播放器、地图等插件会有兼容性问题。
> 所以这也是为什么 1.2 HC 出来之后VD 还在继续被投入使用,以至于 TLHC 发布之后,依然没能完全取代 VD 和 HC 的主要原因,因为目前它们都不是最优解。
而从目前的情况下,`PlatformView` 也成了 Android 平台的沉重包袱,因为多种底层模式在同时工作,并且还在互相「兼容」。
#### API
那么回归到 API 上,在目前 3.0+ 的 Flutter 上同样对应有三个 API ,但是这三个 API 并不是直接对应上述三种模式:
- `initAndroidView` :默认情况下会使用 TLHC 模式,当 SDK 低于 23 或者存在 `SurfaceView` 的时候,会使用 VD 模式兼容
- `initSurfaceAndroidView` 默认情况下会使用 TLHC 模式,当 SDK 低于 23 或者存在 `SurfaceView` 的时候,会使用 HC 模式兼容
- `initExpensiveAndroidView` 强行完全使用 HC 模式
看到没有,这里有一个问题就是:**你其实没办法主动控制是 TLHC 还是 VD ,对于 HC 你倒是可以强行指定**。
另外,不知道你注意到没有,不管是 `initAndroidView` 还是 `initSurfaceAndroidView` ,它们都可能会在升级到新版本时使用 TLHC 模式,**也就是如果你的 Plugin 没有针对性做更新,那么可能会在不知觉的情况下换了模式,从而有可能出现 bug** 。
例如 TLHC 模式:
- 对于 `SurfaceView` 的不支持存在一些特殊情况,假设一开始 `PlatformView` 创建时不存在 `SurfaceView` ,但是后续又添加了 `SurfaceView` ,那么该模式将无法正常工作 [#109690](https://github.com/flutter/flutter/issues/109690)。
- 对于 TextureView 场景,有时候会出现不正常更新的异常情况[#103686](https://github.com/flutter/flutter/issues/103686) 。
现在你看出 PlatformView 的混乱了吧?从底层实现的不统一,到 API 再不同版本下不同的行为变化,这就是目前 Android 在 PlatformView 支持下的混乱生态,同时如果你对于目前 PlatformView 存在的问题刚兴趣,可以查阅以下相关 issue
- [#103686](https://github.com/flutter/flutter/issues/103686)
- [#109690](https://github.com/flutter/flutter/issues/109690)
- [#112712](https://github.com/flutter/flutter/issues/112712)
- [#130692](https://github.com/flutter/flutter/issues/130692)
所以,目前的 Android PlatformView 就给我一种既视感,好比魔兽世界里的平行分支:
- 地狱咆哮喝下了恶魔之血,绿皮吼爷打爆深渊领主玛诺洛斯
- 地狱咆哮拒绝喝恶魔之血,橙皮吼爷打爆深渊领主玛诺洛斯
虽然都是打爆了玛诺洛斯,虽然吼爷结局都一样扑街,但是中间的剧情走向还是有着极大的分歧,所以只能寄希望未来的世界线可以正常「收束」,能有一位「伯瓦尔」来结束这个混乱之治的时代。
![](http://img.cdn.guoshuyu.cn/20230719_N30/image6.png)

214
Flutter-SQS2023.md Normal file
View File

@ -0,0 +1,214 @@
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image1.png)
# 社区说|Flutter 一知半解,带你拨云见月
Hello大家好我是 Flutter GDE 郭树煜,今天的主题是科普向的分享内容,主要是带大家更全面的去理解 Flutter ,尽可能帮助大家破除一些误解,**分享内容不会特别长,但是应该会帮助你从新认识下 Flutter** 。
Flutter 发布至今大概有 6 个多年头,相信现在大家对于 Flutter 也不至于太陌生,但可能有的人对于 Flutter 还处于「一知半解」的状态,所以本次分享的主要目的是给大家普及一些 Flutter 常识,解读一些 Flutter 常见的误解,带你拨云见月,重新认识 Flutter 。
> 所以今天不讲技术实现,只谈风花雪月。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image2.png)
# 从谣言开始
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image3.png)
那首先我们从“谣言”开始,其实 Flutter 从出道以来就一直备受争议,不管是写法还是语言,都在一段时间内饱受“歧视”,如今再回过头来看,会发现这对于 Google 来说是「基础操作」:
> **就像 Android 盘活了 Kotlin 和 Gradle 一样Flutter 也盘活了 Dart ,它们之间有着相辅相成的关系**
Dart 作为 Flutter 的开发语言,它原本处于竞争失利的「雪藏项目」,所以它的没什么历史包袱,可以轻装上阵配合 Flutter 的脚步。
尽管一开始选择 Dart 会导致和 JS 与 Kotlin 等的生态分裂而带来「抵触」,但是正如前面所示,在这一方面,谷歌无疑很擅长盘活,而 Dart 从 Dart 1 到 Dart 3 ,也很好的配合着 Flutter 的脚步在逐步成长。
> 当然,另一个方面,这和传闻中 Dart 项目组就在 Flutter 隔壁大概有关系,至少沟通方便。
当然Flutter 的跨平台设定也给它带来了诸多“负面” 的 buff其中一些谣言在最初的时候可以说十分盛行例如
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image4.png)
其实大家只要稍微思考一下,如果因为是谷歌的技术,就无法上架 iOS 的 App Store 这明显就不合理,而这个谣言更多来自于:
> 因为 Flutter 开发会让 iOS 原生开发流失,所以苹果需要维护自己的开发者。
这里其实是利用了大多数人的误区,不管是使用 Flutter 还是 React Native ,你只要开发 iOS 和上架 App Store ,就不可避免需要 Xcode 和 MacOS ,这对于苹果来说并不是坏事,因为可能更多不是全职的 iOS 开发会投入到 Apple 的体系里,另外:
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image5.png)
Flutter 虽然帮助完成了上层的 UI 和逻辑业务,但是底层交互,构建打包和平台支持都离不开原生开发的支持, 所以:
> Flutter 会在一定程度挤压 iOS 的生态,但是从另一个角度,也会让其他生态的人接触和使用 iOS **甚至 Flutter 的 Plugin 一定程度还在为 Swift 的推广提供支持**。
甚至之前还有因为 “Flutter 使用的是 Material 风格的 UI ,所以无法上架” 的言论,按照这个理论,那么作为头部应用的 Twitter ,浓厚的 Material 风格产品应该也在此列才是,并且 Flutter 也有 Cupertino 风格的控件,只是没想到产品设计风格都会被用来变成一个打击的理由。
> **用 Flutter 开发出什么风格的应用,完全看你的使用方式**
事实上从 Flutter 的 UI 实现上Flutter 和 React Native 的不同之处就在于它的控件都是独立于平台的自渲染,所以它更像 Unity 一样的独立游戏引擎,既然 Unity 都不是问题,那么 Flutter 自然也只是 App Store 技术生态下的一个小点缀。
**更何况 App Store 的核心是应用提成**,上架应用越多,需要经过平台的抽成可能就越多,只要你符合 App Store 的 Guideline 要求,你用什么技术上架并不会成为上架不了的原因。
最后,再介绍一个新鲜落地的消息,前几天微信发布了全新的小程序新渲染引擎 Skyline 正式版,宣称加载速度提升 50% 以上,而网友通过抓包,确认是 Skyline 的渲染是 [flutter 绘制方案](https://gist.github.com/OpenGG/1c71380dd1401b7c93d39294772344fe) 。
| ![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image6.png) | ![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image7.png) |
| ----------------------------------------------------------- | ----------------------------------------------------------- |
> 微信小程序使用 Flutter 渲染,**更主要是其渲染更加精细可控,同步光栅化的策略,可以更好解决局部渲染、原生组件融合**等问题。
当然,这里微信小程序使用的是 flutter 的渲染模式,而不是 flutter 开发方式,开发依然是原来的套件,只是 Skyline 做了一层转化,这也是大厂对于 Flutter 常见的玩法。
# Flutter 的定位
接下来就不得不聊一聊 Flutter 的定位,其实 Flutter 在发布之后,因为跨平台的“招黑” 属性,自然不可避免会有围绕跨平台来做焦虑的自媒体,这和前段时间 AI 盛行的“焦虑”氛围类似。
既然前面有“尬黑”,那么肯定也有“尬吹”的存在,如下图就是 Flutter 前期最常被用的“尬吹”场景:
> 这些“尬吹”不仅会给人带来焦虑更会激起大家的抵触心理潜移默化让人觉得Flutter 的定位就是过来抢夺 Android 和 iOS 生态,是不死不休的局面。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image8.png)
但是其实 Flutter 的定位并非如此,虽然 Flutter 的发展在不可避免会有挤压到部分原生开发的情况,但是 Flutter 的实际目的并不在此,或者说我们的视角和 Flutter 团队并不在一个层面。
举个例子在之前我发起过一个简单问卷如下图所示关于「Flutter 你更常用的 IDE 工具」的统计下,有 71.9% 选择是使用 Android Studio 作为开发工具。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image9.png)
但是对于官方统计的数据,可以看到这个情况只能对应到 “部分” 场景,例如 “软件工程师”和“技术主管” 等头衔的人会更可能使用 Android Studio 开发 Flutter 。
> 这在我们的认知里貌似没什么问题,因为感觉 flutter 开发很多都是从 Android 开发转换过的,所以更习惯用 Android Studio 好像没什么毛病。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image10.png)
但是其实总体趋势还是在 VS Code ,因为在全球,除了开发者之外,还有使用 Flutter 的「非开发者存在」他们的角色可能是学生、设计师、PM 等非专业开发人员,而 Flutter 团队的理念是:
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image11.png)
**Flutter 不会在专业和非专业开发人员之间划出一条强硬的界限,因为今天的许多学生和业余爱好者开发人员明天也可以成为专业人士**。
> 例如 Flutter 上饱受争议的 GetX 的作者,他主职业是一个名律师,但是热爱开发,他花了十年时间从事网络安全和网络犯罪工作,后面开始学习了 Dart 语言,然后学习了 Flutter进而开始从而开源活动。
**所以官方的市场定位绝不是去掠夺和转化 Android 、iOS 、Web 和 PC 等原生开发者**,它有更多的愿景,是希望可以提供给非专业人士拥有开发的能力,所以 Flutter 的发布会上,也多次提及了 FlutterFlow 等地代码平台,另外也有类似 Daro 的 Flutter 的低代码平台。
Flutter 作为跨平台 UI 框架,它提供的是全平台的 UI 和逻辑支持,通过降低开发门槛和提高代码复用率来拓展技术能力,这是 Flutter 团队的愿景,只是回归到我们开发者的视角,就可能变成一种挤压。
不过另一方面,随着技术的成熟,开发的门槛本来就会越来越低,例如:
> 现阶段 Android 和 iOS 工作生态的变化,并非归咎于跨平台框架的出现,而是技术越来越成熟,资源越来越多,开发门槛也自然随着下降,现在开发 Android 起手一套官方 Jetpack 体系,完善程度确实不像曾经 13 年那样什么都需要靠“自己”。
随着设备的硬件支持也越来越强,官方配套越来越齐全,跨平台的需求自然也就越来越多,因为提高资源的重复利用是生产中的一个必然趋势,所以就像 Compose 也在走跨平台的支持
> 所以从我的角度去看,跨平台并不是完全是挤压,相反还有帮助 A 平台的开发者可以接触到 B 平台的东西,反之也是,一定程度也是提高了 AB 两个平台的活跃能力。
另外Flutter 这个定位从最近的 Web 更新也可以看出来,在 Flutter 3.10 关于 Web 的发布里,官方就对 Flutter Web 有明确的定位:
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image12.png)
> **“Flutter 是第一个围绕 CanvasKit 和 WebAssembly 等新兴 Web 技术进行架构设计的框架。”**
Flutter 团队表示,**Flutter Web 的定位不是设计为通用 Web 的框架**,类似的 Web 框架现在有很多,比如 Angular 和 React 等在这个领域表现就很出色,而 Flutter 应该是围绕 CanvasKit 和 [WebAssembly](https://link.juejin.cn/?target=https%3A%2F%2Fwebassembly.org%2F) 等新技术进行架构设计的平台。
所以 Flutter 本身的定位就不是去竞争和转化开发者,例如在 Web 领域它更多是对前沿技术的尝试Dart 已经开始支持直接编译为原生的 wasm 代码,一个叫 WasmGC 的垃圾收集实现被引入到标准里,未来因为 WebGPU 的落地,**WebGPU + WebAssembly 在未来也可能让 Flutter Web 支持全新的 Flutter Impeller 引擎**。
> PS这里的 WebGPU 来自 W3C 制定的标准,与 WebGL 不同WebGPU 不是基于 OpenGL ,它是一个新的全新标准,可以提供在浏览器绘制 3D 的全新实现,它属于 GPU硬件显卡向 Web浏览器开放的低级 API包括图形和计算两方面相关接口。
所以 Flutter 可能会转化一些原生开发但是并不会冲击原生开发Flutter 的愿景和目的都不是这个。
# Flutter 的局限和未来
说了那么多正面的,那 Flutter 有什么样的局限?其实是框架就会有它的局限性,而 Flutter 的局限很大程度来自它的优势。
这里我们简单回顾下跨平台的框架的发展:
- 最初的跨平台框架如 Cordova ,是通过 `WebView` 加载本地 h5 资源实现 UI 跨平台,然后 js bridge 和原生平台交互调用 Plugin 来实现原生调用
- 第二阶段是为了性能而出现的 React Native 和 Weex ,通过统一的前端标签控件转化为原生控件进行渲染,从而提高了性能,不过因为是通过原生控件渲染,所以存在 UI 会有一致问题和兼容适配的成本。
- 第三阶段出现在了 Flutter 上Flutter 通过独立渲染引擎,利用 GPU 直接渲染控件,从而避免了代理渲染的性能开销,同时也保证了不同平台上 UI 一致。
这么看好像 Flutter 更优秀,那为什么说局限性?
## 局限
因为这种独立渲染 UI 的实现,让 Flutter 的 UI 渲染树脱离了原生平台,这时候,如果你需要在 Flutter 里接入原生控件,那么接入成本和对性能的影响都会比较大。
事实上开发 App 就不可避免需要接入 WebView 、地图、广告、视频等原生 UI ,所以在很长一段时间, Flutter 每个版本都在为接入原生控件而努力调整,比如 Android 至今已经有个三次较大的 PlatformView 接入变化,目前基本上算是可以实现接入使用,但是还存在一些局限,例如:
> 3.10 ,当 `PlatformViews `出现在屏幕上时Flutter会限制 iOS 上的[刷新率以减少卡顿](https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fflutter%2Fengine%2Fpull%2F39172),当应用显示动画或可滚动时,用户可能会在应用出现 `PlatformViews` 时注意到这一点。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image13.png)
详细的我们就不展开,感兴趣可以看我理解发过的文章:
- [Flutter 3.0下的混合开发演进](https://juejin.cn/post/7113655154347343909)
- [告别 VirtualDisplay ,拥抱 TextureLayer](https://juejin.cn/post/7098275267818291236)
- [Flutter 深入探索混合开发的技术演进](https://juejin.cn/post/7093858055439253534)
另外还有的局限就是「热更新」,虽然说 Flutter 不是不能支持热更新,甚至 Flutter 团队的元老之一 Eric 在离职之后,也创立了 [shorebirddev](https://github.com/shorebirdtech/shorebird) 来支持 Flutter 热更新,但是 Flutter 本身的属性,其实非常不适合热更新。
> 因为 Flutter 在 Release 下是编译为 AOT 的可执行二进制代码,而下发二进制代码本来就是 Google Play 和 App Store 的禁止行为,当然国内也有很多通过下发各种文本,然后通过映射或者代理的方式去更新 Flutter ,不过这种操作一定程度上提高了维护成本和降低了性能。
而 shorebirddev 就更大胆,直接 fork 了一个 Flutter 分支进行魔改,从而支持热更新的能力,为此目前还不支持使用了 shorebirddev 的 Flutter App 去上架市场。
> 当然,未来有可能会支持,比如官方已经表示可以上架的 iOS 正在支持中。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image14.png)
还有一个局限就是文本排版和编辑Flutter 在文本排版上的局限,因为是全新的独立引擎,所以它拥有一套自己独立的文本渲染和排版逻辑,而和发展沉淀多年的 Web 排版相比可以说是足足的「萌新」不管是在多语言中文的兼容上还是在字体字形的问题上Flutter 都存在需要时间去调整的细节问题。
> 甚至因为最近换了新的 Impeller 引擎的原因,文本上需要修复的问题会更多
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image15.png)
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image16.png)
例如 Impeller 标签下就有很多关于文本和排版相关的问题。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image17.png)
另外,前面我们介绍过,未来 Flutter Web 更多会投入到 Wasm 里,这也会引起一些兼容问题,例如这个页面是采用 wasm 渲染的 Flutter Web 页面,但是当我们用插件翻译页面内容时,可以看到只有标题被翻译了,主体内容并没有。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image18.png)
这是因为此时 Flutter Web 的主体内容都是 canvas 绘制,没有 html 内容,所以无法被识别翻译,另外如果你保存或者打印网页,也是输出不了完整 body 内容。
另外一个 Web 上的局限就是 SEO Flutter 会让谷歌在查看网站并认为它是 3-8mb如果使用 google 洞察力测试一个网站,会需要你的网站应该小于 1.8mb,并且必须在 1 秒内加载才能排名。
Google 和 Bing 这样的搜索引擎会根据速度、编程语言、图像自动大小、CDN 和最终内容对网站进行排名Google 要求机器人视图和用户视图相同。
> 例如使用 [seo_renderer](https://pub.dev/packages/seo_renderer) 可能会违反谷歌关于伪装的 SEO 指南,虽然看起来本质上是在 `Text `中添加“替代文本”,但对于 Googlebot 返回的是完全不同的 HTML 内容,这就是问题的症结所在。
最后, Flutter 开发的中后期肯定还是需要原生开发,这个是无法回避的问题,就算社区插件生态再丰富,总归抵不住产品和老板的天马行空,比如:
> 虽然社区已经有完善的第三方生物认证插件,但是我最终不得不 fork 一个份自己过来修改已满足产品的特殊需求。
所以 Flutter 本身就具备它的局限性,即是优点也是缺点,是否选择 Flutter 主要从你的产品定位和需求出发去判断。
## 未来
最后不得不谈 Flutter 的未来Flutter 目前最大的改动就是全新的底层 Engine Impeller 。
作为 skia 的替代,这是 Flutter 团队发展的必经之路,就如前面所说, skia 本身有着许多历史包袱和平台需要考虑,没办法和 Flutter 步步紧扣,所以 Flutter 选择开始全新的自研 Impeller 是一个非常重要的投资,它也给了 Flutter 团队更多的可能。
> 正如 React Native 也自研了 Hermes ,然后 JSI 开始支持同步调用一样。
目前 Impeller 已经在正式版支持 iOS Android 也正在适配,它也带来了不少「阵痛期」的问题,比如一些渲染字体的问题,但是这个投资带来的收益是可观的,也许未来还可能诞生一个全新的通用 “skia” 。
另外就是游戏,近两年 Google I/O 都通过 Flutter 发布了对应的游戏,例如 Pin 和 Card 游戏,这两个游戏也展示了 Flutter 在游戏领域的可能Flutter 的天然设定让它有用和 unity 相似的场景,所以通过 Flutter 来实现游戏也是官方展示的另外一种可能。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image19.png)
![](http://img.cdn.guoshuyu.cn/20230728_JJ/image5.gif)
可以看到 Flutter 在这两年的 I/O 上,把 Flutter 的游戏能力发挥的很不错,从整体 UI 和游戏体验上都很优质,特别是今天的游戏结合了 AI 生成和设计,可玩度得到了进一步提升。
最后就 Flutter 团队在 Flutter Forward 上展示的 3D 能力,因为在此之前 skia 是 2D 引擎,所以无法完整支持 3D 的场景,而现在 Flutter 为我们展示了它未来 3D 渲染的可能,虽然还只是一个 Demo ,属于画饼阶段,但是这也是 Flutter 未来的一个期待。
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image20.gif)
![](http://img.cdn.guoshuyu.cn/20230801_SQS2023/image21.gif)
所以未来 Flutter 上的 3D 游戏支持也可以期待,不过前提也是 Flutter 能把现在已有的坑都填完先。
好了,今天分享的内容就这些,谢谢大家。

View File

@ -187,6 +187,10 @@
* [Flutter 3.10 适配之单例 Window 弃用,一起来了解 View.of 和 PlatformDispatcher](Flutter-310Win.md)
* [Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel ](Flutter-N25.md)
* [Flutter 小技巧之 InkWell & Ink 你了解多少](Flutter-N26.md)
* [Flutter 小技巧之滑动控件即将“抛弃” shrinkWrap 属性](Flutter-N28.md)
* [Flutter III 之你不知道的 PlatformView 的混乱之治](Flutter-N30.md)
* [掘力计划Flutter 混合开发的混乱之治【直播回顾】](Flutter-JL2023.md)
* [社区说|Flutter 一知半解,带你拨云见月](Flutter-SQS2023.md)
[Flutter 工程化选择](GCH.md)

View File

@ -233,6 +233,14 @@
* [Flutter 小技巧之 InkWell & Ink 你了解多少](Flutter-N26.md)
* [Flutter 小技巧之滑动控件即将“抛弃” shrinkWrap 属性](Flutter-N28.md)
* [Flutter III 之你不知道的 PlatformView 的混乱之治](Flutter-N30.md)
* [掘力计划Flutter 混合开发的混乱之治【直播回顾】](Flutter-JL2023.md)
* [社区说|Flutter 一知半解,带你拨云见月](Flutter-SQS2023.md)
* [Flutter 工程化选择](GCH.md)
* [Flutter 工程化框架选择——搞定 Flutter 动画](Z1.md)
* [Flutter 工程化框架选择 — 搞定 UI 生产力](Z3.md)