Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

2023-05-30 0 746

对采用过 Flutter 的合作开发而言,假如对在 Flutter 混和合作开发中,透过 PlatformView 网络连接原生植物命令行的形式并不孤单,而假如你从 Flutter 1.20 以后就早已开始采用 Flutter ,所以假如对 Android 上 PlatformView 的各式各样新体验难题有过真切的感受,比如说:<a href=”https://juejin.cn/post/6858473695939084295″> WebView 里插入按键的难题。

❝⚠️特别注意:variations有精采

从两个难题早已开始

碰巧前段时间一名好友在 Flutter 2.10.1 上采用 webview_flutter 和 flutter_pdfview 试验时再次出现了如下表所示的难题:

attachToContext: GLConsumer is already attached to a context at android.graphics.SurfaceTexture.attachToGLContext(SurfaceTexture.java:289)

「因此话虽如此那个难题来给我们科学普及下 Flutter 里 PlatformView 与此同时实现的社会变迁和今后修正」,具体而言那个难题的直接其原因其原因是:

❝virtual displayes 和 hybrid composition 三种 PlatformView 与此同时实现混和采用。

即使从 Flutter 2.10 早已开始,非官方的 Plugin 如 webview_flutter 默都是采用 hybrid composition的与此同时实现,而服务器端的 flutter_pdfview 现阶段却是采用从前的 virtual display ,这就再次出现了三种 PlatformView 与此同时实现与此同时再次出现的情形。

总之,非官方在 2.10.2 版的 #31390 上复原了那个难题, 难题的其原因是:「当 rasterizer 各项任务运转相同的缓存时,GrContext 会被再次建立,从而引致 texture 变为没初始化的状况,从而多次重复初始化 attachToGLContext 引致崩盘」。

❝因此先期非官方复原那个难题,是在 attachToGLContext 以后,假如 texture 早已 attach 过,就先初始化 detachFromGLContext 展开释放出来,从而防止了初始化 context 的难题。

但从难题上看,其实那个难题并不是 2.10 才会再次出现,而是只要在 SurfaceTextureWrapper 那个对象存在时 ,混和采用 virtual displayes 和 hybrid composition 就能引发那个 bug 。

❝SurfaceTextureWrapper 是非官方用于处理同步的难题,即使当 SurfaceTexture被释放出来时,由于 SurfaceTexture.release 是在 platform 缓存被初始化,而 attachToGLContext 是在 raster 缓存被初始化,相同缓存初始化时可能引致:「当 attachToGLContext 被初始化时 texture 早已被释放出来了,因此需要 SurfaceTextureWrapper 用于与此同时实现 Java 里同步锁的效果」。

因此假如在低版不想升级,所以可以选择所有 Plugin 都采用 virtual display 模式或者 hybrid composition 模式,比如说 webview_flutter 就提供了 WebView.platform 用于用户自由选择 PlatformView 的渲染模式。

「总之一般情形下我是更建议我们现阶段都采用 hybrid composition 模式,虽然三种模式都有潜在难题,但相比起来现阶段 virtual display 带来的性能和按键难题会让人更难以接受」。

区别和重构

其实在以后的 《 Hybrid Composition 深度解析》 里就介绍过它们与此同时实现的区别,这里再结合上面的难题,从不一样的角度介绍下它们的与此同时实现差异和社会变迁。

VirtualDisplay

一般 dart 代码里直接采用 AndroidView 的我们就可以简单认为是采用 virtual display ,比如说flutter_pdfview 1.2.2 版 , 这种与此同时实现形式是 「透过将 And

Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

❝VirtualDisplay 类似于两个虚拟显示区域,需要结合 DisplayManager 一起初始化,一般在副屏显示或者录屏场景下会用到。VirtualDisplay 会将虚拟显示区域的内容渲染在两个 Surface上。

关于 virtual display 与此同时实现,假如你需要对应路径去调试难题,可以参看如下表所示流程:

Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

HybridComposition

采用 hybrid composition 相对会比直接采用 AndroidView 在代码上更复杂一点, 需要采用到PlatformViewLinkAndroidViewSurfacePlatformViewsService 这三个对象,具体而言我们要建立两个 dart 命令行:

透过 PlatformViewLink 的 viewType 注册了两个和原生植物层对应的注册名称,这和以后的 PlatformView 注册一样;然后在 surfaceFactory 返回两个 AndroidViewSurface 用于处理绘制和接收触摸事件;最后在 onCreatePlatformView 方法采用 PlatformViewsService 初始化 AndroidViewSurface 和初始化所需要的参数,与此同时透过 Engine 去触发原生植物层的显示。
Widget build(BuildContext context) { // This is used in the platform side to register the view. final String viewType = hybrid-view-type; // Pass parameters to the platform side. final Map<String, dynamic> creationParams = <String, dynamic>{}; return PlatformViewLink( viewType: viewType, surfaceFactory: (BuildContext context, PlatformViewController controller) { return AndroidViewSurface( controller: controller, gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}, hitTestBehavior: PlatformViewHitTestBehavior.opaque, ); }, onCreatePlatformView: (PlatformViewCreationParams params) { return PlatformViewsService.initSurfaceAndroidView( id: params.id, viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: StandardMessageCodec(), ) ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) ..create(); }, ); }

假如透过上面的难题来做个直观的对比,就会是如下表所示图所示的变化:

Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

采用 hybrid composition 之后, 「PlatformView 是透过 FlutterMutatorView 把原生植物命令行 addView 到 FlutterView 上,然后再透过 FlutterImageView 的能力去与此同时实现图层的混和」,简单解释是:

rmView 上渲染 Flutter 自己的 Widget 时,Flutter 就会透过再叠加两个 FlutterImageView 来承载那个 Widget 。

Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

举个例子,如下表所示图所示,其中:

两个灰色的 Re 是原生植物的 TextView;蓝色、黄色、红色的是 Flutter 的 Text ;
Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

从渲染结果上可以看到:

灰色的原生植物 TextView 透过 PlatformView 直接就透过原生植物的 addView 方法添加到 FlutterView 上;而红色的 Flutter 的 Text 命令行即使和 PlatformView 没交集,因此却是 Flutter 原本的渲染逻辑;黄色和蓝色的 Flutter 命令行,即使和 PlatformView 有交集,因此透过新的 FlutterImageView 做承载渲染。

采用 hybrid composition 后,在 Engine 去 SubmitFrame 时,会透过 current_frame_view_count 去对每个 view 画面展开规划处理,然后会透过判定区域内是否需要 CreateSurfaceIfNeeded 函数,最终触发原生的 createOverlaySurface 方法去建立 FlutterImageView。

for (const SkRect& overlay_rect : overlay_layers.at(view_id)) { std::unique_ptr<SurfaceFrame> frame = CreateSurfaceIfNeeded(context, // view_id, // pictures.at(view_id), // overlay_rect // ); if (should_submit_current_frame) { frame->Submit(); } }

假如有需要调试 hybrid composition 相关功能的,可以参考如下表所示路径, 和 virtual display 相同之处是在 create 之后的路径产生了变化 , 更多详细演示可见:https://juejin.cn/post/6858473695939084295#heading-2

Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进
Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

结论

因此可以看到,「hybrid composition 保留了更多的原生植物命令行效果,也节省了渲染成本」 ,总之现阶段 PlatformView 还有两个比较尖锐的难题,例如#95343 的闪动难题,那个难题看来在今后会透过更改渲染形式和纹理优化来解决。

是的,还其原因是性能等难题,因此「新的 PlatforView 与此同时实现来又要来了,从上面提到的 #31198已经合并可以猜测,下两个稳定版中,现在的 virtual displayes 与此同时实现将不复存在,从而替代的是透过新的 TextureLayer 与此同时实现,今后不排除 hybrid composition 也会被取消,不知道我们此刻心情如何?」

Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进

简单说是:

新的 PlatformViewWrapper 会替换掉原本 virtual display 里 SurfaceTextureWrapper相关的逻辑,通ition 现阶段看起里仅是更换了称谓,只要核心逻辑没大变动;

而假如今后 PlatformViewWrapper 的与此同时实现效果良好 ,可以猜测 hybrid composition 模式也会从而退出历史舞台,因此唯有感慨, Flutter 的技术重构速度真的好快。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务