从 Flutter 的视频渲染到 App 落地经验

avatar

3月23日周六,由 RTC 开发者社区主办的 “RTC Dev Meetup 北京站”如约举行,超过100位求知若渴的开发者参加了活动。来自 LeanCloud、声网 Agora、阿里、美团点评的资深工程师,与他们共同分享了 Flutter 开发中的实践经验。

我们在这里回顾一下每个演讲中的部分干货。想进一步了解更多内容细节?请看到文末,那里会有你想要的。

郑鹏:浅谈跨平台方案的适用场景

LeanCloud iOS 高级开发工程师郑鹏从框架特点、实现原理与现状角度对比分析了 React Native 与 Flutter。

React Native 是 Facebook 在2015年推出的一套开源跨平台方案,这个方案可以说在移动平台上一个真正意义上的跨平台方案,因为它能够达到技术原生应用的一个体验。它有三个主要特性:

  • 能使⽤ JavaScript 和 React 在移动平台构建原⽣应用
  • 支持热加􏰀载(Hot Reloading)
  • 同一套代码可以运行在 iOS、Android 以及其它平台

在 React Native 的官方项目作品展里面有这样一个应用叫做 Discord。2018年的时候,Discord发表了一篇博文,聊了聊他们眼中 React Native 的优缺点,总结如下:

谈及 React Native 的现状,郑鹏表示,大家对于 React Native 已经形成了比较统一的认识,它没有性能方面的问题,并且能快速地构建UI以及原型等。但交互场景太过复杂,或者需要大量的计算资源的话,React Native 就会遇到瓶颈。同时在跨平台的兼容性上也表现的差强人意。尽管有这样多的问题,Facebook也是声明了他们会对于React Native的底层进行改造以此提升性能,虽然官方没有给出一个具体的时间点,但是这似乎意味着React Native的未来还是可以期待的。

在跨平台方案经过了 React Native 这波浪潮之后,Google 在2018年年底正式推出了一个看起来更有野心的一个方案,就是 Flutter。Flutter 的特点主要有四点:

  • 能使用 Dart 以及 React 风格的组件在移动平台构建原生应用
  • 支持热加􏰀载(Hot Reloading)
  • 同一套代码可以运行在 iOS、Android 以及其它平台
  • 比 React Native 更好的性能表现

Flutter虽然看似解决了React Native要面临的很棘手的一些问题,但是Flutter毕竟推出的时间还没有那么长,还没有经过市场的考验,所以Flutter本身还是有一些问题的:

  1. 如何兼容应用层的一些特性。例如 密码自动填充功能,如果想要实现这个特性,那么 flutter 可能要采用 RN 类似的方案,或者用户自己在这部分直接使用原生的接口。
  2. flutter 底层的渲染引擎仍然是 OpenGL,但是 iOS 已经迁移到了 Metal,废除了 OpenGL,那么从这种紧急态度来看,Flutter 什么时候迁移。
  3. Google 以往推出过很多技术、产品,但最后都慢慢消失或被并入某个新项目,而Flutter 未来是否会进入这个“怪圈”也是一个问题。

张乾泽:Flutter实时音视频技术实践

声网 Agora 高级架构师张乾泽分享了在 Flutter 上的实时音视频技术实践。声网在上个月应开发者的要求,发布了声网 Agora Flutter SDK,一个封装了声网 Agora SDK 的Flutter 插件,能让开发者在 Flutter 上实现实时视频通话。那么如何通过 Flutter 来开发一个视频通话应用?会遇到什么问题?从这个演讲中你会找到答案,他分享了可以实现该场景的两种方法,以及 Flutter 渲染的原理。

首先,他介绍了一下 Flutter 的架构逻辑。如果比较熟悉 Flutter 的朋友可能知道,Flutter 的渲染方式与 React Native 最不一样的地方就是它自己的一些原生控件上没有利用系统本身提供的一些接口、控件,比如说 UI View 或 Android 上的一些 View。它自己里面会建立一个 Layer Tree,Flutter 自己来进行渲染,它把这些数据或者渲染结果发到 Skia,由 Skia 引擎渲染处理为 GPU 数据,最后通过 GL 或 Vulkan 发给 GPU。

图:Flutter 渲染机制

当我们在实现一个视频通话应用的时候,我们可以利用 Flutter 自身组件来实现很多基本的功能,比如App 的一个脚手架,还有利用组件来画出界面上的按钮、菜单栏。而视频的编解码、实时传输我们可以交给 Agora SDK 来解决。那么关键的问题在于如何在 Flutter 上渲染视频。

在 Flutter 里有一个组件叫 Video Player,其中有一个 Texture Widget,我们可以通过 Native 端来提供视频数据给这个 Texture,然后通过它来进行渲染。以 iOS 为例,iOS需要提供CVPixelBufferRef,它可以将渲染出来的数据供给Texture Widget,然后Texture Widget就可以把你提供的这些数据显示出来。在我们传输数据的时候会需要将其与 TextureID 绑定,这样一来,可以在同一个界面上出现多个 Texture,也就是说能显示多个视频通话窗口。在其中,声网 SDK 的 AgoraVideoSink 接口里可以提供一个回调,这个回调会把它收到的所有视频数据通过你想要的格式传给 Texture。

图:iOS 的渲染

在 Flutter 1.0中新增的 PlatformView 也可以实现这个场景。PlatformView 在 iOS 和 Android 上分别叫做 UIKitView 和 AndroidView,它可以让你直接创建一个 UIView。我们在Plugin 中有一个ViewFactory,它可以针对不同平台返回一个你需要的 View。最后,在一个分辨率设置较低的状态下进行了视频通话,分别对比了两种实现方法的性能。结果显示PlatformView的性能消耗跟直接用Native接我们SDK的性能比较相近。

王璟瑤:Flutter B端落地和高可用——票务APP应用实践

阿里现娱无线端基础线负责人王璟瑤来自大麦网。大麦网采用Flutter在一个独立的APP上进行了落地。他的分享主要分成四个部分,一是大麦网的落地情况,二就是组件化集成,包括集成、编译构建、调试方面的经验,第三是Flutter作为开发的基础能力,第四是高可用部分。他重点讲解了组件化集成部分。

大麦的 App 分为 B 端和 C 端。他们首先选择了在用户量相对小一些的 B 端落地了 Flutter。随后也在 C 端的进行了落地。

如上图是组件化的结构图。中间 Flutter Container 相当于跟原有 Native Bundle 平行的业务单元。因为我们要单独地编译Flutter大的代码,所以还有一个 Flutter Host 模块。下面还有很庞大的 Common 层。Flutter 内部有一些基础的网络联网、图片显示或一些常有的存储组件,但是用的时候可能你们会需要做增强、网络、图片,像我们用的二维码,基于一些增强的组件来实现的,我们以 Common 层作为承载。

工程依赖可以看到两个工程组件化的形式,我们的根工程基于上面安卓叫 Portal,iOS是 DMPortal,分别有对应的 Common 和 Flutter container、Flutter Host,外面是这个 Host 编译完成之后把相关的产物打包提交到 Flutter Container 去。iOS 是基于软链接跟原来的工程做并联,Android 则相对复杂一些,都是在命令行里完成的。

图:优化后的编译构建

如上图是我们优化之后的编译构建模型。因为我们要解决能运行的问题,所以我们需要编译Engine。以Android这边举例子的话就是我们可能会改变原有标准工程上依赖于Gradal的实现,大量的逻辑会通过脚本的方式做构建,然后做Engine的拷贝,最终我们会打包出一个Bundle AAR,然后再完成整个工程的构建。

除此之外,王璟瑶分享了包括Engin适配、混合页面栈、UI代码组织等方面的干货内容,由于篇幅有限,我们在这里不一一细说。

严涛:美团外卖商家Flutter混合工程实践

美团点评iOS高级开发工程师严涛从工程管理、基础设施建设、业务实践等方面,分享了Flutter在美团外卖商家端上的落地经验。

从工程管理来讲,总共有四类工程:

  • Flutter Application:标准的Flutter App工程,包含Dart层和Native平台层
  • Flutter Plugin:Flutter插件工程,包含Dart层与Native平台层的实现
  • Flutter Module:Flutter组件工程,仅Dart层,Native平台层为隐藏工程
  • Flutter Package:纯Dart组件工程,仅包含Dart层实现

美团外卖需要将Flutter集成到现有的Native工程中。对于这类需求,Flutter官方提供了一套通用方案:

Android端

  • 在settings.gradle中注 include_flutter.groovy 脚本
  • 在需要依赖的module中build.gradle添加project(‘:flutter’) 依赖

iOS端

  • Podfile中注 podhelper.rb脚本,在pod install时会执 该脚本
  • 在iOS构建阶段Build Phases中注入构建时需要执 的Xcode_backend.sh脚本

但这个方案并不适用于美团,因为在第一阶段中,Flutter只是App中的一小部分,并不需要全部人员都做Flutter开发,所以他们希望少改或不改工程配置。另一方面,在当时公司的打包机器上还未配置Flutter的环境。所以官方的方法并不完全使用。他们的解决方案是将Flutter产物组件化,原 程调整为通过Pod对Flutter组件依赖。

美团在Flutter 1.0之前就开始着手开发。从他们的经验来看,Flutter页面首次创建时间较长,对页面启动时间要求比较高的业务,可以考虑集成 flutter 1.0 及其以后版本。

美团看中Flutter就是看中了它的性能,它有自己的一些UI线程和GPU的线程,它有自己独立一套的渲染逻辑,它脱离了Native这一侧的局限。

花絮

  1. 这次活动感受到开发者满满的热情,活动前被一波一波的要求增开名额直至再次满额。而后,又有许多开发者联系,表示:“是自己喜欢的技术,即使是站着也希望可以来听”!

  2. 现场5、60岁的大叔参加,咳咳,当然是一位资深的技术总监啦,真的炒想点赞!

  3. 自己不能来的开发者,妻子来帮忙听了全场,然后帮忙要PPT等现场资料,超感人有没有!

由于篇幅有限,我们没有详细回顾每一个演讲的内容细节。想了解更多,可以下载演讲 PDF(只提供演讲人允许公开的内容)。你还可以在这里回帖提问,我们会请演讲人帮助解答。