今日头条 字节跳动 Flutter架构实践

持续更新--请小伙伴关注! 喜欢的话给一个赞吧!

本文结尾有福利!!

1
移动跨平台技术探究

◆ 为什么需要跨平台?

今日头条 字节跳动 Flutter架构实践

◆ 跨平台技术是如何发展起来的?

今日头条 字节跳动 Flutter架构实践

◆ 跨平台技术选型有哪些?

今日头条 字节跳动 Flutter架构实践

◆ Flutter有什么独特优势(为什么选择Flutter)?

今日头条 字节跳动 Flutter架构实践

◆ 为什么说Flutter是高性能的,体现在哪里?

今日头条 字节跳动 Flutter架构实践

2

Flutter引擎原理剖析

先来看看Flutter的技术架构图:

C++引擎四个核心线程

Flutter 里四个核心线程:平台线程、UI 线程、GPU 线程、IO 线程,它们的职责都是不一样的:

★ 平台线程(PlatformThread)对应着安卓和 iOS 的主线程。

★ UI线程(UI Thread)针对安卓本身的主线程,它就是一个独立的线程。

★ GPU线程(GPU Thread)运行在 GPU 上的线程,它主要是处理 Skia 相关的任务。

★ IO线程(IO Thread)主要处理IO有关的任务,比如:图片编解码等。

具体引擎架构图,如下图示所示:

今日头条 字节跳动 Flutter架构实践

Flutter如何编译成两个平台的应用程序

今日头条 字节跳动 Flutter架构实践

首先看下面的引擎代码是公共的部分,用于把程序的源代码编译Android和IOS两个平台的应用程序。中间左侧绿色部分Flutter针对Android生成的一些文件,然后最终通过引擎会编译生成Android的APK安装包,中间右侧蓝色部分是Flutter针对IOS平台生成的一些文件,然后最终通过引擎会编译会生成IOS平台的安装包。

线程通信(混合开发必须了解的难点)

今日头条 字节跳动 Flutter架构实践

这里以Android为例,对照Flutter做一个讲解。Flutter里面的线程主要依赖于Dart里面的一些API,比如我们常用的异步任务里面,需要用到:MicroTask和Future,就是非常重要和关键的。

我们可以看到技术是相通的,Android里面是一个Handler,对应一个Looper Thread,然后是一个MessageQueue,然后里面存放的是Message。很巧妙的是Flutter也有类似的做法,Flutter有一个Looper线程,主线程复用了Native的,然后为其他三个线程创建独立的Looper。不过与Android不同的是:Flutter用的是两个队列,一个是微任务队列(MicroTaskQueue),一个是普通延迟任务队列。Flutter会先处理为任务队列,再去处理普通任务队列。类比Android来讲,图中的TaskRunner类似于Handler,PostTask就是把一个消息放到一个消息队列的过程。和Android的Handler是很类似的。所以在学新技术的时候,举一反三,懂得变通才能学的更好。

Dart虚拟机

同一个进程里可以有很多 Isolate,两个 Isolate 的堆是不能共享的。Dart开发团队早就考虑到了交互的问题,于是就设计了一个VM Isolate,它是一个用户Isolate之间交互的桥梁,运行在 UI 线程中的。我们可以把数据放在内核态,因为这个内核态可以共享数据,然后把数据放到另一方的队列中,另一方就可以拿到和使用这些数据了。熟悉Android的朋友们应该听起来很熟悉,这就非常类似我们熟知的“进程间通信”。

今日头条 字节跳动 Flutter架构实践

可能这样讲还不是很清楚,具体流程是什么样的呢?请看下图:

今日头条 字节跳动 Flutter架构实践

Isolate1是发送方,创建一个SendPort ,Isolate2是接收方,创建一个ReceivePort。我们创建一个 Isolate的时候,它里面有一个 worker 线程,worker 线程里面可以放入Task。SendPort调用send方法,发送数据到PortMap里面,这个里面每一个port对应一个Isolate 的 MessageHandler,这个Handler包括两个内容:普通的消息队列,一个是 OOB 高优先级消息,数据放入队列顺序有优先级区分。最后消息被封装成一个 MessageTask,传送到另一个Isolate里面去。回想一下是不是类似于Android的消息队列?

Platform Channels

今日头条 字节跳动 Flutter架构实践

Flutter提供了Channel是用于和Native功能做交互。Android这边使用MethodChannel,IOS这边使用FlutterMethdChannel。最终Flutter通过衔接两个平台,使用统一的规范去衔接两个平台,暴露出一些函数和接口,然后就可以很容易的使用Flutter去调用Native的功能了。这个依赖于开发者的水平,需要对Android或IOS比较了解才能更好的写出插件出来。pub.dev上面也有很多开源库,不过往往开发中需求总是在变更的,开源库远远达满足不了实际开发需求的功能点,所以还是需要自己掌握Platform Channels的知识点比较好。

3字节跳动在Flutter架构上的实践

下面来看字节跳动主要做了哪些架构实践,请看下图:

今日头条 字节跳动 Flutter架构实践

从上图中还是可以看到字节跳动做了很多基础工作的,比如:容器化、混合工程、渲染、包体积、编译优化、多端一体化等。看上去确实感觉是很多东西的。下面简单的介绍其中比较关键的几个:

容器化架构

今日头条 字节跳动 Flutter架构实践

个人感觉所谓“容器化”,就类似于原生平台的组件化或者业务分层架构的思想。就是为普通业务打造可扩展的接口和行为准则。不过这个Flutter容器化架构要适应Android和IOS两个平台,然后针对不同的平台的业务行为需要定义统一的标准和规范以及封装了一些通用业务模块功能(其中的某些可以看做是基础业务的基类),比如:图片调用,直接去这里面的协议层,直接调用就可以了,内部都封装好了,直接传参调用,这里面有默认的适配,你也可以自定义。有了“容器化”的架构,平台基础API的差异性就不需要考虑了,开发者只管调用内部的功能模块或者接口即可快速开发新需求功能。

多端一体化实践

今日头条 字节跳动 Flutter架构实践

这个就不用多说了,就是写一个应用可以同时运行在Android、IOS、Web上面,省去了大量的开发周期,多端一体化结合了Flutter,以及Flutter Web,然后定制化了一些内部引擎和功能模块的架构,最终打造出了这套多端一体化的工程体系架构。

监控体系

今日头条 字节跳动 Flutter架构实践

Flutter自带的性能监控工具颗粒度是很粗糙的,用的是物理平均,而不能反映真实的每一帧实时统计。UI线程和GPU线程的处理方式不一样,这样物理平均确实是不直观的做法。

业界很多公司通用的做法是框架层去统计UI线程耗时时间,消息 post 到 UI,然后再post到GPU。但是这种做法有两个缺陷:一个是等待时间没有考虑进去,一个是UI 线程非常快,但是 GPU 线程非常慢,UI 线程向 GPU 线程跑消息时最多 Post 两个消息,这时候 GPU 线程依然处理不过来,UI 线程就不会 Post 消息,但是 UI 线程体现不出来。

字节跳动采用的是“高精度无侵入性能监控方案”:引擎层提供了一套机制,可以知道绘制多少帧,统计你发了多少信号,统计 GPU 线程。另外“无侵入”体现在:框架系统会自动识别性能监控滚动会在什么时候开始,什么时候结束。

Flutter Turbo

今日头条 字节跳动 Flutter架构实践

这个主要是性能提升的方案,比如:消息调度、GC抑制、关闭Semantics、关闭抗锯齿等,另外为了提高性能,内部有一个 Benchmark 跑分,有了这些方案支持,可以大大的提升应用程序额性能。

图片透传优化方案

今日头条 字节跳动 Flutter架构实践

我个人觉得这个方案还是挺不错的,非常有借鉴价值,值得学习和研究一下。现有的方式 Image.network加载网络图片,传入一个路径就可以加载了,然后Dart底层引擎层做解码操作。另外外接纹理方案也是不错的,也是可以实现的,但是它没有在这个基础上进行改造,性能上还有提升空间。字节跳动的透传方案是这样的:使用框架加载图片,然后生成Bitmap,然后Native和Dart VM共享Bitmap,而不是直接的数据传过来的,然后Dart引擎再转成Pixel buffer,这样一来对性能有很大的提升。包体积优化

今日头条 字节跳动 Flutter架构实践

大概有这些优化:做了编译优化;对Flutter产物的数据端做了压缩,对Skia做了裁剪,不需要的东西删掉了,引擎库对一些功能三方库也做了裁剪。

【虽说看的云里雾里,感觉还是很厉害的样子。类型一万个:“卧槽,这么牛逼!”】

今日头条 字节跳动 Flutter架构实践

在这次会议上的第3个主题演讲中,来自字节跳动的专家还专门对包体积优化做了讲解,我会在后面的文章再整理一下分享给大家。

启动速度优化

修改了引擎代码,对启动速度做了优化,几乎提升了1倍。(虽然很牛逼,但是看不到摸不着,也不知道是如何修改的,我只能说希望早点贡献给Flutter社区,我们这些吃瓜群众都来享一下福,沾一点光啊。)

持续更新--请iOS的小伙伴关注! 喜欢的话给一个赞吧!

作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:761407670 进群密码“亮子”,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!

提供:音视频,逆向安防、Swift、算法、架构设计、多线程,网络进阶,还有底层、Flutter等资料

摘自:字节跳动技术团队

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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