闲鱼开源之FlutterBoost混合开发框架

诞生背景

具有一定规模的App通常有一套成熟通用的基础库,一般需要依赖很多体系内的基础库。那么使用Flutter重新从头开发App的成本和风险都较高。所以在Native App进行渐进式迁移是Flutter技术在现有Native App进行应用的稳健型方式。闲鱼在实践中沉淀出一套自己的混合技术方案。

framework简介

新一代Flutter-Native混合解决方案。 FlutterBoost是一个Flutter插件,它可以轻松地为现有原生应用程序提供Flutter混合集成方案。FlutterBoost的理念是将Flutter像Webview那样来使用。在现有应用程序中同时管理Native页面和Flutter页面并非易事。 FlutterBoost帮你处理页面的映射和跳转,你只需关心页面的名字和参数即可(通常可以是URL)。

基本原理
  • flutter 原理
flutter 技术栈主要由 C++ 实现的 Flutter Engine 和 Dart 实现的 Framework 组成(其配套的编译和构建工具我们这里不参与讨论)。Flutter Engine 负责线程管理, Dart VM 状态管理和 Dart 代码加载等工作。而 Dart 代码所实现的 Framework 则是 业务接触到的主要 API,诸如 Widget 等概念就是在 Dart 层面 Framework 内容。
一个进程里面最多只会初始化一个 Dart VM。然而一个进程可以有多个 Flutter Engine,多个 Engine 实例共享同一个 Dart VM。
我们来看具体实现,在 iOS 上面每初始化一个 FlutterViewController 就会有 一个引擎随之初始化,也就意味着会有新的线程(理论上线程可以复用)去跑 Dart 代码。Android 类似的 Activity 也会有类似的效果。如果你启动多个引擎实例,注 意此时 Dart VM 依然是共享的,只是不同 Engine 实例加载的代码跑在各自独立的 Isolate。

flutter java混合开发 flutter混合开发框架_Dart

实现方式

前面我们提到多引擎存在一些实际问题,所以闲鱼目前采用的混合方案是共享同一个引擎的方案。这个方案基于这样一个事实:任何时候我们最多只能看到一个页面,当然有些特定的场景你可以看到多个ViewController,但是这些特殊场景我们这里不讨论。

我们可以这样简单去理解这个方案:我们把共享的Flutter View当成一个画布,然后用一个Native的容器作为逻辑的页面。每次在打开一个容器的时候我们通过通信机制通知Flutter View绘制成当前的逻辑页面,然后将Flutter View放到当前容器里面。

  • flutter-boost主要概念
  • 引擎深度共享

主要思路是由 Native容器 Container 通过消息驱动 Flutter 页面容器 Container,从而达到 Native Container 与 Flutter Container 的同步目的。我们希望做到 Flutter 渲染的内容是由 Naitve 容器去驱动的。
简单的理解,我们想做到把 Flutter 容器做成浏览器的感觉。填写一个页面地址, 然后由容器去管理页面的绘制。在 Native 侧我们只需要关心如果初始化容器,然后 设置容器对应的页面标志即可

  • Native 层概念
    体系结构
  • Container:Native容器,平台Controller,Activity,ViewController
  • Container Manager:容器的管理者
  • Adaptor:Flutter 是适配层
  • Messaging:基于 Channel 的消息通信
    Dart 层概念
  • Container:Flutter 用来容纳 Widget 的容器,具体实现为 Navigator 的派生类
  • Container Manager:Flutter 容器的管理,提供 show,remove 等 Api
  • Coordinator: 协调器,接受 Messaging 消息,负责调用 Container Manager
    的状态管理。
  • Messaging:基于 Channel 的消息通信
性能相关

在两个 Flutter 页面进行切换的时候,因为只有一个 Flutter View 所以需要对上一个页面进行截图保存,如果 Flutter 页面多截图会占用大量内存。所以flutterBoost采用了文件内存二级缓存策略,在内存中最多只保存 2-3 个截图,其余的写入文件按需加载。这样我们可以在保证用户体验的同时在内存方面也保持一个较为稳定的水平。
页面渲染性能方面,Flutter 的 AOT 优势展露无遗。在页面快速切换的时候, Flutter 能够很灵敏的相应页面的切换,在逻辑上创造出一种 Flutter 多个页面的 感觉。

FAQ
  1. 混合开发后跨平台的优势就没有了,为什么还有接入flutter呢? 纯粹是为了技术积累吗?

混合开发是为了逐步的使用Flutter替代现有的原生页面,针对替换的页面依然是只需要一套Flutter代码,所以其跨平台的优势还是存在的,毕竟现有项目太大,不可能完全重写,只能逐步替换,直至完全改造完成;另外,如果是新项目就不用混合开发了,直接使用Flutter开发即可。

  1. 为什么不用flutter 官方的集成方案?

这个方案有一个巨大的缺点,就是在原生和Flutter页面叠加跳转时内存不断增大,因为FlutterView和FlutterViewController每次跳转都会新建一个对象,从而Embedder层的AndroidShellHolder和FlutterEngine都会创建新对象,UI Thread、IO Thread、GPU Thread和Shell都创建新的对象,唯独共享的只有DartVM对象,但是RootIsolate也是独立的,所以Flutter页面之前的数据不能共享,这样就很难将一些全局性的公用数据保存在Flutter中,所以这套方案比较适合开发不带有共享数据的独立页面,但是页面又不能太多,因为创建的Flutter页面越多内存就会暴增,尤其是在iOS上还有内存泄露的问题。

####### 相关链接
framework地址flutter官方集成方案搭建flutter混合开发环境的脚手架工具

flutter-boot 的补充:
对于flutter官方的混合工程项目,我们在体验后发现有如下的问题:
1. 文件或配置的添加为手动添加,流程较长
2. 不支持在 flutter 仓库下运行原生工程
3. 不支持 flutter 以独立代码仓库部署时的远端机器构建
因此在 flutter-boot 脚手架中,为了解决这些问题,我们把混合工程的部署分为 create,link,remotelink,update 四个过程。