头条 Flutter iOS 混合工程实践

体验 Flutter

从 App Store 下载或更新头条(6.9.2 或以上版本),找到 懂车帝 -> 热门车型,点击打开后即可体验 Flutter 的页面效果。

由于前期业务改造顺利,线上 Crash 少,性能良好,目前我们正在进行小视频模块的 Flutter 重构,即将上线。

本文主要介绍头条 iOS 端在接入 Flutter 的过程中,选择的技术方案,遇到的问题和未来的计划。虽然是以 iOS 为例,但很多内容都是双端通用的。

Flutter 基础

为了方便对 Flutter 零基础读者阅读本文,首先介绍一些 Flutter 的基础知识。

当我们写完 Dart 代码后,需要编译后才能给客户端使用。Flutter 的产物分为两种模式,一个是 Debug 模式,采用 JIT(Just In Time)的方式,类似于解释型语言,好处是可以支持热更新,方便调试。另一种是 AOT(Ahead Of Time)模式,类似于编译型语言,好处是性能比较好。

因此在开发中,我们一般使用 Debug 模式的产物来提升调试效率,正式上线后再换成 Release 模式获得极致的性能。不管是哪种模式,在 iOS 下的产物都是三个(安卓类似):

  1. App.framework:和 flutter 的业务逻辑相关,在 Debug 模式下就是一个很小的空壳,在 Release 模式下包含全部业务逻辑
  2. flutter_assets:也和 flutter 的业务逻辑相关,在 Debug 模式下包含全部业务逻辑,在 Release 模式下很小。
  3. Flutter.framework:实现 Flutter 框架自己的逻辑

iOS 工程接入 Flutter 的已有方案

目前主流的方案中主要有两种,一种在 Google 的官方文档里 ,它最大的问题在于, 需要创建一步 BUILD PHASE 调用 shell 脚本去编译 Flutter。编译 Flutter 的过程需要本机有 Flutter 环境才行。

这显然是不能接受的。其实我们先不考虑 Flutter 这件事,不管是搭建什么类型的混合工程,都一定要保证以下两点:

  1. 对原生工程无侵入:原生工程可以增加组件的依赖,但不能修改主工程的配置,更不能让原生工程对环境产生新的依赖。
  2. 方便调试:不管是原生工程开发,调试新接入的模块(比如 Flutter),还是模块开发调试原生工程,都应该支持断点调试。

很明显,官网的方案不满足第一点要求,我们不能让每个参与原生工程开发的同学,本机都安装 Flutter 环境。

Flutter 的官网教程 中可以看到,它支持 flutter run 命令或者从 IDE 启动 iOS 工程。其实只要观察一下 ios 目录下的 Runner.xcworkspace 工程就会发现,Flutter 项目运行的就是这个工程。当然如果直接把我们的 iOS 工程拷贝过来是无法运行的。

至少在目前最新的 dev 分支(Tag:v0.10.0)上是不行的,因为 flutter 的代码中写死了工程的名字就是 Runner,可以验证一下:

这也就催生了目前主流的,也是闲鱼最先介绍的方案,魔改 Flutter 源码,让它能运行自己的工程。然而个人觉得这种方式还是太 trick,主要有两个问题:

  1. 后续如果 Flutter 升级了,还得把修改的部分应用到新的分支上去,并且修复冲突。
  2. 如果公司或者业内有别的团队要用,接入成本比较高。

头条的混合工程方案

观察一下 Runner 的工程结构:

再看一眼 Flutter 编译脚本就会发现,这一步并不是必须放在主工程的 BUILD 阶段进行。只要拥有 Flutter 的编译产物,项目就可以接入 Flutter 的功能了。因此头条选择的方案是:

  1. 利用 flutter build iosflutter build ios --debug 命令,先后构建两种模式下的产物并上传到 CDN
  2. 构建一个 Pod,并且让 Pod 依赖上述产物

在第一步中,运行 flutter build ios 实际上会依赖 Runner 工程,相当于是我们借助这个空壳去得到产物。不过要想编译通过,还需要做如下两个微小的改动:

  1. 修改项目的 Bundle ID,使用自己的证书。否则无法通过签名
  2. 打开 Xcode -> File -> Workspace -> Setting,把 BUILD_SYSTEM 切换为 Legacy,否则会产生编译错误

第二步中,重点在于如何让 Pod 动态的下载资源,因为需要指定使用哪个版本,哪种模式的 Flutter 产物。我们目前的策略是在打包机器上使用 Release 模式产物,在开发机器上使用 Debug 模式产物。

至于动态指定版本号,可以这样写:

s.prepare_command = "bash ./BDFlutterDownload.sh"
s.vendored_frameworks = 'Framework/*.framework'
s.resources = 'Framework/flutter_assets'

通过 prepare_command 语法,可以在 Pod Install 的过程中执行 shell 脚本,把产物下载到 Framework 文件夹中,只要把版本号写到脚本中,并且及时更新就可以了。

调试 Flutter

上述方案解决了 Flutter 工程接入的问题,因为是编译后的资源接入,我们还需要保证 Flutter 开发的同学可以正常调试。这里以最新的 dev 分支举例(Tag:v0.10.0)。

如果是 Flutter 开发的同学,不关心 iOS 开发的细节,可以找到打包后的 app 文件,然后使用 ​ flutter run --use-application-binary​ 指定被调试应用的路径:

如果是 iOS 开发的同学,使用 Xcode 运行项目即可。这两种方式下,都可以看到本地调试的端口(图中的 57674)。

如果是使用编译好的 app 来运行,可以直接使用 r/R 来实现热刷新/热重启。如果使用 Xcode 运行项目,需要先使用命令: ​flutter attach --debug-port=57674 ​。

如果需要在 iOS 侧打断点,必须用 Xcode 运行项目。如果需要在 Dart 侧打断点,可以利用 IDE 的 Debug 功能。这里以 VSCode 为例,首先安装 Dart 插件。


Flutter.png
想学习更多Android知识,或者获取相关资料请加入Android技术开发交流2群:935654177。本群可免费获取Gradle,RxJava,小程序,Hybrid,移动架构,NDK,React Native,性能优化等技术教程!
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容