Flutter 工程化框架选择 — 混合开发的摸爬滚打_platformviewsservice(1)

在 Flutter 里混合原生平台的控件需要通过 PlatformView 进行接入实现,在这方面 iOS 的实现方式一直变化不大,但是在 Android 上不同版本到目前就出现了三种实现逻辑,所以本篇主要介绍 Android 平台如何选择合适的 PlatformView 方案。

抛开最早期如 flutter_webview_plugin 这种直接进行覆盖原生控件的实现不谈, PlatformView 在 Android 上目前官方提供的就有三种实现方式:

  • VirtualDisplays :类似于一个虚拟显示区域,将虚拟显示区域的内容渲染在一个内存 Surface上,然后同步纹理到 Engine ,事实上控件并不在渲染位置。

  • HybridComposition : 通过 addView 直接添加原生平台控件,需要层级覆盖时利用 FlutterImageView 承载 Flutter 控件的渲染进行堆叠,原生控件会在渲染位置。

  • TextureLayer :在渲染位置通过原生的透明 PlatformViewWrapper 做容器,然后通过替换 Canvas 将原生控件的纹理渲染到特定 Surface 上,控件不在渲染位置,但是可以通过父容器做事件拦截。

是不是看完有点懵?不怕后面会有对应的例子解释,不理解也不要紧,这一篇是教你如何选,所以也并不需要真的理解内部是如何实现。

但是上面介绍的这三种实现也是有前提条件的,比如:

  • Flutter 1.2 之前,你只能用 VirtualDisplays
  • Flutter 3.0 之前,你只能用 VirtualDisplaysHybridComposition
  • Flutter 3.3 之前,你只能用 TextureLayerHybridComposition
  • Flutter 3.3 开始,你能用 VirtualDisplaysTextureLayerHybridComposition

是不是觉得有些奇怪,为什么会有奇怪的排列方式?这里面的故事线大概是这样的:

  • 因为 VirtualDisplays 存在触摸事件和键盘等问题,所以通过 addView 进行原生堆叠的 HybridComposition 出现,解决了手势和键盘等问题
  • 因为 HybridComposition 存在一些场景缺陷,比如列表卡顿,渲染线程不同步导致闪动等问题,所以 VirtualDisplays 得以继续服役
  • 3.0 开始默认 VirtualDisplaysHybridComposition 被替换为 TextureLayer ,但是 HybridComposition 实现依旧保留,在使用时需要显式执行 PlatformViewsService.initExpensiveAndroidView 才能使用,因为 TextureLayer 存在没办法替代原生控件 Canvas 的场景,同时 TextureLayer 要求 Flutter Mini SDK API 23
  • 3.3 开始 VirtualDisplays 实现又回来了,因为需要支持 Mini SDK API 23 以下的场景,同时比如 SurfaceView 机制原因,这类场景 TextureLayer 实现没办法直接兼容,所以 3.3 开始在遇到 SurfaceView 实现时 TextureLayer 会切换为 VirtualDisplays 模式

这里面固然有实现成本的问题,同时也有社区把控的问题,才造成了这样“混乱”的局面

上面这么说可能有些抽象,我们再看具体例子,首先看官方的 webview_flutter 实现, 如下表格所示,最初的时候 WebView 插件默认是使用了 AndroidWebView ,也就是 VirtualDisplays 相关的实现;后来有了 HybridComposition 之后就新增了 SurfaceAndroidWebView ,用户在需要时可以根据场景自行切换。

默认判断VirtualDisplaysHybridComposition

这里就不得不提以前的 issue ,如果你的 WebView 存在触摸或者键盘问题就可以通过下述代码来解决,因为正如前面说过, HybridComposition 是通过 addView 的方式添加原生控件,所以能尽可能保存控件本身的特性。

if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
复制代码

而后来 webview_flutter 在更新迭代里默认实现里也修改为了 SurfaceAndroidWebView ,因为 HybridComposition 确实更适合 WebView 的场景,比如 H5 的详情页。

默认判断TextureLayerHybridComposition

上面的例子可能还不够典型,接着我们再看一个典型的例子: MapView ,如下所示,目前国内 Flutter 里常见的地图实现有:

虽然他们都是采用了 PlatformView 的实现,但是选择的实现方式却存在一定差异,而通过这些差异也可以很好比对 PlatformView 实现的区别:

  • 高德 Flutter 插件采用的是 AndroidView 的实现方式,也就是在 3.0 以下是 VirtualDisplays ,在 3.0 以上是 TextureLayer , 从表中的图 2 也可以看到在 Flutter 3.0 MapView 父容器对应的 TextureLayerPlatformViewWrapper
dart 实现TextureLayer

这里额外需要注意的是:由于隐私政策等原因,现在基本地图框架都需要做一定的隐私相关适配,高德也不例外,所以如果想正常使用 SDK ,就需要注意初始化时的适配问题。

对隐私和权限问题感兴趣可以看 《2022 年 App 上架审核问题集锦,全面踩坑上线不迷路》

  • 华为 Flutter 地图插件选择的则是 HybridComposition 的实现方式,注意下图代码里的 initExpensiveAndroidView ,因为现在使用 PlatforViewLink 已经不能作为是否使用 HybridComposition 的判定标准,3.0 开始必须显式配置了 initExpensiveAndroidView 才是 HybridComposition

3.0之前 PlatforViewLink3.0之后 PlatforViewLink + initSurfaceAndroidView3.0之后 PlatforViewLink + initExpensiveAndroidVie
HybridCompositionTextureLayerHybridComposition

HybridComposition 详细实现感兴趣的可以了解:混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进《1.20 下的 Hybrid Composition 深度解析》

  • 百度 Flutter 地图插件采用的是 AndroidView 的实现方式,但是原生端提供了 TextureViewSurfaceView 两种实现选择,这又产生了不同的组合结果。

3.0之前3.03.0之后
VirtualDisplaysTextureLayerSurfaceView 方案无法工作)VirtualDisplays(SurfaceView)/ TextureLayer(TextureView)

从下方的 Layout Inspector 可以看到,在 Flutter 3.3 下,百度地图插件如果使用了 MapSurfaceView 就会采用 VirtualDisplays ,而如果使用了 MapTextureView 就会采用 TextureLayer ,这是为什么呢

SurfaceViewTextureView

前面我们不是说过,Flutter 在 3.0 的时候通过 TextureLayer 取代了 VirtualDisplays ,而 TextureLayer 的实现方式就是通过 PlatformViewWrapper 来替换 child 的 Canvas 从而提取纹理,但是在某些场景下就会有问题,例如 SurfaceView

简单来说,SurfaceView 是比较特殊的场景,本身它具备双缓冲机制,类似于两个 Canvas ,同时在 WMS 有独立的 WindowState , 所以渲染逻辑其实是脱离了原本的 View hierachy ,因此 Flutter 3.0 下的 TextureLayer 的 hook Canvas 实现没办法兼容。

所以在 Flutter 3.3 中 VirtualDisplays 又回来了,作为多年服役的"老将",当运行平台低于 23 或者原生控件是 SurfaceView 时,就会继续降级采用 VirtualDisplays 的相关实现,这也算是折中的实现

SurfaceViewTextureView

如果对这部分感兴趣的可以查阅 Flutter 3.0下的混合开发演进 / Flutter 深入探索混合开发的技术演进

所以现在知道为什么要做这一期了吧?Flutter 的 PlatformView 实现因为历史包袱留下了很多“坑”,不理清楚这些坑,很可能就会让你在遇到问题时找不到方向,总结一下:

  • VirtualDisplays 老骥伏枥,采用的是虚拟显示提取纹理的方式,可能存在手势和键盘问题,适合列表和小控件场景,在 3.0 版本中缺席
  • HybridComposition 在 1.2 版本之后出现,因为是通过 addView 和层级堆叠实现混合,能尽可能保证控件的“原汁原味”,但是性能开销会比较大,不适合列表里使用,在 3.0 之后需要显式调用 initExpensiveAndroidView
  • TextureLayer 在 3.0 版本开始出现,通过 Hook 住控件 Canvas 的方式实现纹理提取,但是需要 miniSDK 23 ,适用于替代 VirtualDisplays 的场景,但是在 3.3 开始遇到 SurfaceView 时会降级为 VirtualDisplays

其实我有预感,在之后的版本这部分逻辑还会出现变化,但是可能 3.0 和 3.3 的发布一样,并不会将这种变更放在 release note 里。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新**

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
[外链图片转存中…(img-Bb7MIMqB-1712834614158)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值