站在巨人的肩膀上

flutter-talk發表於2019-05-23

PonyCui 發表於 2019.05.12

自移動平臺(iOS / Android)誕生以來,跨平臺開發的嘗試從未停止,成功與失敗並存。而 Flutter 的出現並非偶然,是 Google 基於前人長期以來探索的道路,輔以大規模人力、物力創造得到的。

在真正開始 Flutter Talk 之前,我覺得有必要讓大家知道,十多年來前輩們是如何走出這條血路的。

跨平臺方案的演進

WebKit

在初代 iPhone 釋出之時,也就是 iOS 1 的年代,WebKit 技術是全球開發者最為尊崇的跨平臺技術之一。同時,Apple 也致力於推動 WebKit 走向商業化、跨平臺化。你可能不知道的是,在 iOS 6 之前,iOS 應用的渲染引擎就是基於 WebKit,iOS 應用實質上也是一個 WebApp。自那時開始,Chrome、Safari 份額日漸上升,WebKit 功不可沒。

然而,WebKit 終究只是一個瀏覽器渲染引擎,跨平臺方案要求的不僅是通用的渲染方案,其背後的語言層、圖形層以及基礎環境層都佔據非常重要的位置。但是,偏偏就是這些重要的底層元件,各家瀏覽器開發商都有不同的實現方案,通俗來講,就是不相容。

以 WebKit 為基礎的跨平臺方案,終於走向各自為政的道路。iOS 6 以後,WebKit 成為了配角。Android 自此至終沒有將 WebKit 置於正室位置。

WebView

假如 WebKit 不能成為原生元件的唯一渲染引擎,那麼,能否取而代之使用 WebView 作為替代方案?畢竟 WebView 的使用已經有二十多載的歷史了,網頁的編寫也相對簡單,各種瀏覽器廠商也普遍遵循 w3c 和 ecma 規範。

但是,使用 WebView 作為跨平臺方案有一個重大的弊端 —— 無法呼叫原生能力。例如,WebView 要調起原生系統的相機、膠捲,就非常困難。

為了彌補這一缺陷,有了 PhoneGap、 JavascriptBridge 這些方案。然而,Patch 終究只是打補丁,這種小修小補的集合體,最終只能讓『跨平臺』成為一個替補演員的角色。同時,WebView 又是一個黑盒子,一旦出現未知問題,只能乾著急。

Facebook 的主應用在最初的版本就是使用 WebView 進行開發的,然而,在後續的版本中,又完全使用原生重構整個應用了,具體原因?

React Native

React Native 是 Facebook 於 2016 年公佈開源的 Hybrid 開發引擎,其核心思想是希望在 ReactJS 的基礎上,封裝一套 Native 渲染的混合開發框架。React Native 仍然是基於 JavaScript 的跨平臺方案,與 WebView 不一樣的是,渲染層由原生實現。其優點在於,RN 能充分使用原生元件能力,從而減少無謂的元件開發工作。

然而,React Native 有一個致命的缺點 —— 慢!這種慢很大程度是因為 JavaScript 的單執行緒模型造成的,RN 的跨平臺能力,很大程度依賴於 JavaScript 的統一實現,RN 將所有的觸控事件、動畫驅動以及頁面棧都封裝在 JS 內,通過一致的 JS 實現以求達到跨平臺一致性。這是一個極大的矛盾,一方面,我們不應該將過於繁重的工作交給 JavaScript 實現,而一方面,過多的平臺程式碼會使得平臺一致性的特性減弱。

更要命的是,RN JS 執行緒與原生 UI 執行緒並不處於同一執行緒,執行緒間通訊完全依賴以 JSON 為主的序列化、反序列化方式進行。當使用 RN 構建大規模應用時,效能問題更顯突出。

小程式

小程式並不是嚴格意義上的跨平臺開發框架,鑑於小程式產品的成功,仍然有必要在這裡討論一下。小程式實質上仍然是 WebView,沒錯,是 WebView。小程式的核心是敲掉 WebView 的 JS 環境,使開發者無法直接操縱 WebView 中的物件。緊接著,提供一個完全受控的 JavaScript 環境,通過該環境控制多個 WebView 的 DOM 渲染並響應 DOM 事件。

小程式可以很好地執行在受控應用中,但在效能、互動、功能要求更高的場景中,並無太大優勢。筆者認為,小程式是一個好產品,但不是一個好方案。

Flutter

那麼,Flutter 呢?Flutter 比上面所說的各種方案更優秀嗎?在論證 Flutter 是否更優秀前,筆者覺得應該先讓大家知道 Flutter 背後的原理。

原理

Flutter 的原理很簡單,建立一張畫布,並在這張畫布上渲染介面。同時,監聽原生事件,在 Dart 層響應所有觸控事件。這和跨平臺遊戲引擎的原理是一致的。抽象出統一的介面、觸控、互動語言,然後使用一致的渲染引擎呈現最終產物。

簡單的原理背後,總有複雜的實現支撐!

Dart

Dart 是 Google 開發的類似 Java 的一門程式語言,是 Flutter 的基礎執行環境,它支援編譯至 JS / AOT / JIT 多種 Target。 在 AOT Target 下,其執行效率與原生編譯型語言幾乎一致!在 JIT Target 下,又兼有熱更新、熱過載的便利性,使得應用 Restart 更輕鬆。同時,Dart 可以編譯至 JS,使得 Flutter Web 成為可能。

Dart 可以說是精簡版的 Java,如果你有相關的 Java 編碼經驗,應該很容易上手。

Skia

Skia 是 Google 開發的 2D 渲染引擎,是 Flutter 的底層渲染環境,它支援在不同平臺上執行,包括 iOS / macOS / Windows / Android / Linux 等,Skia 同時是 Chrome 的渲染引擎。

藉助 Skia,Flutter 得以在不同平臺上有極為一致的輸出表現。

UIToolbox

在 Skia 與 Dart 之上,是 Flutter UIToolbox,UIToolbox 是基於 Dart 開發的一套全新的介面方案。為何 Flutter 需要一套全新的介面方案?還記得原理中提及到,Flutter 是在一塊獨立的畫布上渲染的嗎,正因如此,Flutter 無法複用 iOS / Android 原生的 UI 元件,必須自行實現一套。

在這背後,是龐大的工作量!

Flutter 完整的實現 Material 和 Cupertino 兩套元件庫,Material 團隊還告知 Flutter 團隊,Flutter 是 Material 的最佳還原。

工具鏈

Flutter 團隊也意識到,編碼工具的易用性對於開發者來說,非常重要!因此,Flutter 團隊花費了大量精力改進 VSCode 和 Android Studio 的外掛表現。今天,你能快速地開始、構建 Flutter 應用,背後負載著 Flutter 工程師無數多個日夜的努力,在此為他們點贊。

總體表現

那麼,將所有的基礎混合在一起,效果如何?

在效能上,能與原生應用並肩嗎?

答案是,能!而且,可能更好!筆者藉助 Flutter 開發了一個完整的應用,從應用的幀率表現來看,Flutter 能在大部分情況下達到 >= 50 FPS 的效果。

同時,Flutter 也很好的避免了 RN 所遇到的困境,Flutter 的主執行緒就是 UI 執行緒,它可以在主執行緒處理 UI 的更新,也可以在主執行緒處理觸控的響應而無須經過複雜的執行緒間通訊。

再者,Flutter 也借鑑了 React 以資料驅動介面的思想,在應用開發的過程中,極大地提升了開發效率。

結論

Flutter 的面世離不開前輩們的努力,同時,也是基於 Google 在語言、渲染等基礎庫上大量的投入下產生的。如此跨時代的跨平臺開發框架,值得各位去嘗試一下。

相關文章