假如你是从 2018 年开端运用 Flutter ,那么相信你关于 Flutter 在混合开发的支撑进程应该会有一个深化的体会,假如你没尽力过这个时期,不要忧虑,经过我过往 PlatformView
的相关文章,你也能够有一个清晰的感触:
- Flutter 3.0下的混合开发演进
- 离别 VirtualDisplay ,拥抱 TextureLayer
- Flutter 深化探索混合开发的技能演进
- HybridComposition 和 VirtualDisplay 的完成与未来演进
- Hybrid Composition 深度解析
- Android PlatformView 和键盘问题
总而言之,现在 Flutter 关于 PlatformView
的支撑,特别是在 Android 渠道上,只能用一个字来描绘:「乱」。

这个「乱」不只是体现在 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 里进行烘托。

问题也很明显,由于控件不会真实存在烘托的位置,所以此刻的点击和对原生控件的操作,其实都是需求由 Flutter 这个 View 进行二次转发,别的由于控件是烘托在内存里,所以和键盘交互需求经过二级代理处理,这就产生了各种键盘输入的异常问题。
键盘问题突出在不同版别的 Android 兼容上。
HC
1.2 版别开端支撑 HC,简略说便是直接把原生控件覆盖在 Flutter 上进行堆叠,假如呈现 Flutter Widget 需求烘托在 Native Widget 上,就选用新的 FlutterImageView
来承载新图层。

好处是原生视图是直接显示烘托,害处便是在 Android 10 之前存在 GPU->CPU->GPU的功能损耗。
别的由于此刻原生控件是直接烘托,所以需求在原生的渠道线程上履行,这和 Flutter 的 UI 线程就存在线程同步问题,所以在此之前一些场景下会有画面闪耀 bug 。
TLHC
3.0 版别开端支撑 TLHC 形式,最初的目的是替代上面这两种形式,怎么办终究只能共存下来,该形式下控件尽管在仍是布局在该有的位置上,可是其实是经过一个 FrameLayout
代理 onDraw
然后替换掉 child 原生控件的 Canvas
来完成混合制作。

所以看到此刻上图
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。 - 关于 TextureView 场景,有时分会呈现不正常更新的异常情况#103686 。
现在你看出 PlatformView 的混乱了吧?从底层完成的不一致,到 API 再不同版别下不同的行为改变,这便是现在 Android 在 PlatformView 支撑下的混乱生态,一起假如你关于现在 PlatformView 存在的问题刚爱好,能够查阅以下相关 issue:
- #103686
- #109690
- #112712
- #130692
所以,现在的 Android PlatformView 就给我一种既视感,好比魔兽国际里的平行分支:
- 阴间吼怒喝下了恶魔之血,绿皮吼爷打爆深渊领主玛诺洛斯
- 阴间吼怒回绝喝恶魔之血,橙皮吼爷打爆深渊领主玛诺洛斯
尽管都是打爆了玛诺洛斯,尽管吼爷结局都相同扑街,可是中间的剧情走向仍是有着极大的分歧,所以只能寄希望未来的国际线能够正常「收束」,能有一位「伯瓦尔」来结束这个混乱之治的时代。
