最近一段時間 Flutter 的技術熱度非常高,經常在逛 Github 的時候瞄到,出現的多了,也就引起了我的興趣;然後來看看這是個什麼玩意。
稍微搜一下大概能知道:
Flutter 是 Google 一個新的用于建構跨平台的手機 App 的 SDK,同時也将是 Google Fuchsia 下開發應用的主要工具。
它在 2017 年釋出初始版本,很明顯是一個為了解決不同平台 App 重複開發的問題,這也不是什麼新技術,類似的還有 React Native、Weex。
簡單說就是達到 “write once, run everywhere” 的目的,怎麼這麼耳熟呢。。。
深入了解可以看一下這篇:為什麼說 Flutter 是革命性的
Dart
Flutter 使用 Dart 語言開發,Dart 可以被編譯(AOT)成不同平台的本地代碼,讓 Flutter 可以直接和平台通訊而不需要一個中間的橋接過程,進而提高了性能。
這裡,有必要提一下 React Native,也是一種流行的跨平台建構方案,是 Facebook 在 2015 年左右搞出來的,要比 Google 早的多。
Facebook 最明智的一點就是讓 RN 采用 JS 作為開發語言。因為 JS 擁有非常好的群衆基礎和較低的學習門檻,是以 RN 不僅可以吸引大量的前端開發者加入,而且可以和 React 社群形成正向互補,進一步鞏固 Facebook 在前端領域的統治力。基本上所有合格的前端開發者都可以低成本的學習并使用 RN 進行跨端開發。
Google 讓 Flutter 采用 Dart 進行開發,可能是基于對未來的判斷,希望 Dart 可以逐漸取代 JS 成為前端的開發标準。實際上 Dart 的文法更接近原生開發語言,用 Java 或者 Swift 的開發者會更加喜歡。
RN 采用了橋接系統服務,順帶将系統 UI 也橋接到了 JaveScript 中,可通過原生 UI 系統進行渲染,效率方面肯定比 Flutter 差一點,但是成熟度與友善程度與新發展的 Flutter 根本不是一個量級,不過後續怎樣我們繼續看吧。
跨平台方案的發展
WebView
第一個跨平台的架構基于 JavaScript 和 WebView,例如 PhoneGap, Apache Cordova, Ionic 等,在蘋果釋出 iOS 之前,他們鼓勵第三方開發者為 iPhone 建構網頁應用程式,是以使用 Web 技術建構跨平台應用程式是順理成章的一步。
我感覺這跟我們之前說的用 HTML5 響應式布局寫差不多,既可以簡單打包成 App,又可以讓手機直接在浏覽器中通路,不過像 JavaScript 這樣的語言很難直接與本地代碼(例如服務)進行通信,是以他們會通過一個在 JavaScript 代碼和原生代碼的“橋梁”進行上下文切換,因為平台服務通常不會經常被調用,是以這并不會導緻太大的性能問題。

React Native
響應式視圖火起來後,他們通過使用從響應式程式設計中借用的程式設計模式來簡化 Web 視圖的建立過程。2015 年, React Native 将響應式視圖的許多優勢帶給了移動應用程式。
因為 JavaScript 時常會通路原生 UI 元件,是以它也必須經過這些“橋接器”,界面上的 UI 控件通常被頻繁地通路(在動畫、轉化或者使用者用手指“滑動”螢幕上的某些東西時,每秒被通路高達 60 次),是以這很可能會導緻性能問題。
這是了解 React Native 性能的其中一個關鍵,JS 代碼和原生代碼本身都是很快的,瓶頸經常發生在當我們視圖從一邊轉向另一邊時。
未來建構高品質的應用程式時,我們必須将使用橋接的次數控制到最小。
橋接器是 RN 的核心,相比 WebView 它不光橋接了系統服務,還把 UI 順便也橋接了過去,這樣寫出來的 UI 最終也會被渲染為原生控件,這也讓它在混合開發的時候變得容易。
對于 JS 開發者來說, 畫 UI 隻需要畫到 Virtual DOM 中,不需要特别關心具體的平台, 還是原來的單線程開發,還是原來 HTML 組裝 UI(JSX),還是原來的樣式模型(部分相容 )。
不過 UI 的渲染是比較頻繁的,想要不卡頓還必須要 60FPS+,這對性能是個不小的挑戰。
因為 RN 是采用 JS 開發,還需要一個 JS 的環境,不過這個不用太操心,想多了解下 RN,可以看一下:React Native運作原了解析
Flutter
和 React Native 一樣,Flutter 也提供響應式的視圖,Flutter 采用不同的方法避免由 JavaScript 橋接器引起的性能問題,即用名為 Dart 的程式語言來編譯。
Dart 是用預編譯的方式編譯多個平台的原生代碼,這允許 Flutter 直接與平台通信,而不需要通過執行上下文切換的 JavaScript 橋接器。編譯為原生代碼也可以加快應用程式的啟動時間。
實際上,Flutter 是唯一提供響應式視圖而不需要 JavaScript 橋接器的移動 SDK,這就足以讓 Fluttter 變得有趣而值得一試,但 Flutter 還有一些革命性的東西,例如它是如何實作 UI 元件的。
元件(Widgets)
這應該是最重要的一塊東西,我們可以輕松的用 Web 技術模拟出原生的界面或者符合預期的界面與動畫,但是讓他們擁有原生元件的特性與流暢度或者事件綁定是比較難的,比較這些模拟的元件最終還是外來物,再說性能方面也是一個問題。
Flutter 的系統架構包含大量賞心悅目、快速、可定制、可擴充的 Widgets。沒錯,Flutter 不需要使用系統 UI 元件(或 DOM WebViews),它自帶了 Widgets。
Flutter 将 UI 元件和渲染器從平台移動到應用程式中,這使得它們可以自定義和可擴充。Flutter 唯一要求系統提供的是 canvas,以便定制的 UI 元件可以出現在裝置的螢幕上,以及通路事件(觸摸,定時器等)和服務(位置、相機等)。
Dart 程式和執行資料編碼與解碼的原生平台代碼之間仍然有一個接口(參考上圖中的藍綠色部分),但這能比 JavaScript 橋接器快幾個數量級。
Flutter 最大的改進之一就是它的布局,它大大簡化了布局的“規則”,例如我們都用過的 CSS3 定義了 375 個屬性,規則可以互相影響甚至發生沖突,要處理他們之間的關系非常複雜,然而我們常用的一些規則占比非常小,是以 Flutter 改變了傳統的布局方式。
體驗過 Flutter 的基本都能感覺到界面是非常順滑的。
虛拟DOM
現有的響應式 web 視圖庫都引入了虛拟 DOM,DOM 代表 HTML 的文檔對象模型,虛拟 DOM 則代表 JS 利用 DOM API 抽象出來的版本。
在響應式 Web 視圖(由 ReactJS 和其他系統實作)中,虛拟 DOM 是不可變的,每次更改,所有的東西都得重建。系統将虛拟 DOM 與真正的 DOM 進行比較,生成一組最小的更改,然後執行這些更改,以更新真正的 DOM。最後,平台重新繪制真實的 DOM 到畫布中。
這聽起來增加了很多額外的工作,但它是值得的,因為操縱 HTML DOM 是非常耗費系統資源的。
React Native 也做類似的工作,但是是在移動應用程式當中進行的。它會操控移動平台上的原生元件而不是 DOM。它建構一個 UI 元件的虛拟樹,與原生元件進行比較,并隻更新已更改的部件。
結語
其實無論 RN 還是 Flutter 都有相當大的野心實作全平台制霸。除了 Android、iOS 平台之外,RN 已經可以通過第三方工具支援 Windows UMP、Web、Desktop、macOS,甚至近期京東開源的 Alita 項目已經實作 RN 到微信小程式的打通。
RN 當下還是最成熟的一個解決方案,畢竟已經發展的多年,資料也比較多,即使這樣官方 Github 也有不少的 issue 未處理,更不要說新興的 Flutter,不過從長遠看,Flutter 也必将是一場革命吧。
最後我想說,JS NB!,加上 Node、Vue、React、Element 的加持,還有什麼不能寫,前端、後端、桌面 GUI、App 通吃,不知道明天又會被玩出什麼花樣來。