今日頭條 字節跳動 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閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374