讓我們在2019年重新認識 Flutter
現在是2019年,讓我們認真來看看備受矚目的 Flutter,重新認識一下它。本文首先簡要回顧移動開發(跨平臺開發)的發展歷史,并談談不同階段跨平臺解決方案的優劣;接著從 WHAT / HOW / WHY 三個方面詳細來聊聊 Flutter,并結合簡單的 Dart 代碼說說開發者該如何上手,隨后展示幾個 Demo App;最后會就本次分享進行一段小結。Flutter 到底是什么,它的來臨對前端又意味著什么?讓我們接著往下看。
一、移動開發歷史回顧
當下的移動互聯網仿佛給我們營造一種假象—— Android 和 iOS 已經存在許多年。而回首過往,才發現 Android 剛和我們度過第一個十年。十年前我們更多的討論桌面應用與 Web,十年后我們專注在一個小屏幕,享受移動應用給我們帶來的多彩世界。
移動應用(即我們日常所說的「原生」應用程序),通常是指某一移動平臺所特有的應用程序。通過使用特定平臺所支持的開發工具和語言進行開發,你可以直接調用系統提供的一些 SDK API。當下流行的移動操作系統中,我們使用 Java 或 Kotlin 調用 Android SDK 開發 Android 應用,或通過 Objective-C 或 Swift 調用 iOS SDK 開發可以上架 App Store 的應用。凡事沒有銀彈,移動開發也是如此。簡要來看,原生應用開發具有以下優勢:
1. 可獲取平臺全部開放功能,比如攝像頭,藍牙等;
2. 用戶訪問應用的感受通常是速度快、性能高、體驗好的;
而其缺點也很明顯,主要有:
1. 為特定平臺開發,綜合成本高,不同平臺維護需要人力成本;
2. 動態化能力弱,大多數情況下,新功能更新只能發版;
說到動態化,一次編碼便可運行在任何平臺的 Web 讓我們記憶深刻。而針對移動端存在的這些問題,為了在提高體驗的同時賦予應用動態化能力,誕生了一批又一批的跨平臺移動開發解決方案。根據實現方式的不同,我將它劃分為三個時代:
1. 青銅時代。在該時代的框架主要采用 Webview 容器(廣義)進行內容渲染,并借助原生代碼預置用以暴露給 JavaScript 調用的一部分系統能力,而這類協議則為我們通常說的 JavaScript Bridge;這個時代的框架在 Web 與 Native 間還有比較明顯的界限,大家各司其職(UI 渲染與系統功能調用);
2. 白銀時代。在這個階段我們仍然用 JavaScript 開發,但繪制已經交由 Native 接管,展現在用戶面前的 UI 借助的是 JavaScript VM 的解析與 Native Widgets 的組合展示;
3. 黃金時代。不同于前一個時代,由于 Native Widgets 在 UI 上的「不盡如人意」,這個時代對方案起了一個新概念——自繪引擎,通過它在底層的繪制實現上來抹平不同平臺上界面開發的差異,UI 上真正做到了「每一個像素點可控」。雖然涉及到平臺層時還是需要原生開發介入實現相應插件,但這已是三種跨平臺移動開發方案中最靈活的一種了。
二、問題
我們常說 Web 最終將一統天下,也常聽見 Web 在離我們遠去的聲音。但至今在終端 UI 上也沒有迎來一個完美的解決方案,這是因為在不同階段、不同實現上,都存在很多現實問題。讓我們再回顧一下這三個時代:
1. 青銅時代:采用 Webview 渲染的方案雖然成本低、部署迅速,但仍難以 cover 富交互的用戶界面與復雜手勢的快速響應;
2. 白銀時代:利用 JavaScript 調用 Native 代碼操作 UI 的方案雖然解決了不少渲染問題,但是跨平臺 Native Widgets 的差異仍然是個問題,這使得我們在 UI 上要做一些「妥協」,而存在于 JavaScript 與 Native 間的通信成本在一些場景下仍會使這種方案成為「累贅」;
3. 黃金時代:直接使用底層 API 進行繪制在執行效率上大步邁進,看似已經是終極解決方案,但大家是否想過,為什么被世人「不堪」的 Web 存在這么多年,不但沒有消亡反而愈發繁榮,以至于我們常說「任何能用 JavaScript 實現的應用,最終都必將用 JavaScript 實現」;
注:「累贅」問題可詳見 Flutter 中文網關于移動開發技術一章的 介紹 。
其他還有一些問題值得思考,比如:
- 在今天,針對每個移動平臺單獨開發一套代碼,成本是否太高?
- 自繪引擎在操控 UI 上已經足夠自由,但當初這種解決方案為什么沒有火起來?
- 快速開發與部署、多端可訪問的 Web 開發模式,在當下以及未來是否還會持續過去的增長勢頭?
三、What is Flutter
帶著這些疑問,我們走進全文的主角——Flutter。從2017年第一個 Alpha 版到上個月 Flutter Live 發布的 1.0 版本,Flutter 正獲得越來越多的關注目光。很多聽到這個詞的同學可能會感慨,似乎 UI 技術迎來了終極解決方案。我們先看看官方對它的定義:
Flutter 是 Google 用以幫助開發者在 iOS 和 Android 兩個平臺開發高質量原生 UI 的移動 SDK。Flutter 兼容現有的代碼,免費并且開源,在全球開發者中廣泛被使用。
看看 Flutter GitHub Star 的變化趨勢,會發現每一個陡增都預示著 Flutter 的一次重要版本發布。在深入了解之前,我們來看幾個用 Flutter 做的 App,感受下官方所述的 Beautiful 到底是什么樣子的。
四、How is Flutter
看上去好像還不錯,但 Flutter 究竟有哪些與眾不同呢?我們按照官方描述的四個方面,分別來說說:
1. Beautiful - Flutter 允許你控制屏幕上的每一寸像素,這讓「設計」不用再對「實現」妥協;
2. Fast - 一個應用不卡頓的標準是什么,你可能會說 16ms 抑或是 60fps,這對桌面端應用或者移動端應用來說已足夠,但當面對廣闊的 AR/VR 領域,60fps 仍然會成為使人腦產生眩暈的瓶頸,而 Flutter 的目標遠不止 60fps;借助 Dart 支持的 AOT 編譯以及 Skia 的繪制,Flutter 可以運行的很快;
3. Productive - 前端開發可能已經習慣的開發中 hot reload 模式,但這一特性在移動開發中還算是個新鮮事。Flutter 提供有狀態的 hot reload 開發模式,并允許一套 codebase 運行于多端;其他的,再比如開發采用 JIT 編譯與發布的 AOT 編譯,都使得開發者在開發應用時可以更加高效;
4. Open - Dart / Skia / Flutter (Framework),這些都是開源的,Flutter 與 Dart 團隊也對包括 Web 在內的多種技術持開放態度,只要是優秀的他們都愿意借鑒吸收。而在生態建設上,Flutter 回應 GitHub Issue 的速度更是讓人驚嘆,因為是真的快(closed 狀態的 issue 平均解決時間為 0.29天);
注:數據源自五、Why use Flutter
為什么要使用 Flutter?僅僅因為他是「Google 下一代操作系統」Fuchsia OS 的內置 UI SDK 么?
回答 ,我嘗試簡單解讀一下:
讓我們看的再詳細一些,上一張 Flutter 系統架構圖,根據之前在問題「開發跨平臺app推薦React Native還是flutter?」下的從上至下分別為 Framework,Engine 和 EmEmbedder:
- Framework 層是框架使用者需要直接面對的,包含文本/圖片/按鈕等基礎 Widgets、渲染、動畫、手勢等。如果你寫 Flutter 應用,那么大致可以理解為調用這些 package 然后再用 Dart 「拼裝」些自己的代碼。
- Engine 層使用 C++ 實現,這一層包含 Skia,Dart 和 Text。后兩個不太熟,說說 Skia。這是一個二維圖形庫,提供了適用于多種軟/硬件平臺的通用 API,既是 Chrome,Chrome OS,Android,Firefox,Firefox OS 等產品的圖形引擎,也支持 Windows 7+,macOS 10.10.5+,iOS8+,Android4.1+,Ubuntu14.04+ 等平臺;Dart 可能包含 Dart Runtime 等(JIT/AOT),Text 則負責文字渲染部分。
- Embedder 是一個嵌入層,做的事情是 Flutter to Platforms。比如渲染 Surface,線程設置,插件等。Flutter 的平臺層很低,比如 iOS 只是提供一個畫布,剩余的所有渲染相關的邏輯都在 Flutter 內部,而這就是 Flutter 所宣傳的可以精準控制每一個像素的原因;但不可否認,對于插件部分,還是需要特定操作系統底層的建設(比如支付、地圖等)。
有沒有對 Flutter 更清晰一些?
如果說再舉一點可以打動你使用 Flutter 的地方,那就是 animation 了。利用 Flare 你可以輕松構建支持 Flutter 的動畫效果。這有點像十年前用 Flash 做關鍵幀動畫的感覺。
當然,Flutter 和 Dart 團隊的不斷努力和優化更是說服你選擇 Flutter 的理由之一。在剛不久前結束的 D2 上,Google 工程師介紹了為什么 Flutter 可以如此快,比如 Dart 在運行時更少的 malloc,Flutter 應用運行時有更少的處理環節(跳過 Android/Chromium),Flutter 在渲染布局上更高效的遍歷過程等等。
面向未來,讓你在 Flutter 上下注的因素更少不了 HummingBird 和 Flutter for Desktop。STAY TUNED FOR GOOGLE I/O 2019!
六、Code with Dart
利用 Flutter 提供的腳手架,做一個簡單的 Demo 你甚至只需要寫更改兩個文件:main.dart 和 pubspec.yaml。作為前端,你可以將它們比做 index.js 與 package.json 吧。詳盡的代碼可見 https://gist.github.com/hijiangtao/2b58ab07d3d7ed96aa0f868140c906e5 .
七、Take away
人的記憶是短暫的,說了這么多,如果說本文想給大家帶去些什么思考的話,我覺得可以總結成下面五句話:
1. RECAP / 在移動端跨平臺開發方案的歷史更迭中,我們從 Webview 加 Bridge 到 React Native 再到如今吸引大家目光的 Flutter,終端 UI 技術是否真的迎來了終極解決方案我們不得而知,但通過簡單回顧了這條歷史長河上出現過的幾場光輝,希望借他們的發展身影能給從事前端的大家帶去一些跳出業務代碼的全局思考;
2. WHAT / Flutter 是什么:Google’s Portable UI Toolkit。它起源于移動端,但目光遠不止眼前的茍且。
3. HOW / Flutter 有四個特點,分別是 Fast, beautiful, productive 以及 open。這些能力源于其背后 Dart、skia 和更多技術的支持,了解這些有助于幫助我們更清楚一個完整的 UI 系統由哪幾個部分構成,以使我們對上層建筑有更立體的感受。
4. WHY / 為什么選擇 Flutter,我在分享中介紹了不少原因,有系統設計的分析,有開放的學習態度,也有面向未來的 Mobile and beyond.
5. END / 如果你對 Flutter 感興趣請不要忘記對 Google I/O 保持關注。對身邊的新技術時刻保持好奇,做一個快樂的 Geek!
大浪淘沙,下一個十年我們又將身在何方?希望我的分享能讓你有所收獲。文中有誤的地方歡迎評論指出,關于 Flutter 的更多內容歡迎一起討論。謝謝。
背后的故事1:很多前端工程師在最初聽到 Flutter 時都充滿疑惑,為什么 Flutter 選用了 Dart,而不是使用 Web 技術或者是 JavaScript 語言來實現 Flutter 框架。其實 Flutter 中有不少內容便是吸收自 Web 社區,比如 tree shaking 和 hot reload。但 Flutter 另一個鮮為人知的故事是團隊中大部分成員都具有 Web (Chromium) 背景。如果你看過 Flutter Live,應該知道 Flutter 與 Dart 團隊的人數并不多,大致就頭像墻中列出的那些,在最初設計上,他們也曾反復考慮 Web 技術,而在語言選型上也考慮過 JavaScript。應該不會有人比他們更了解 JavaScript 與 Web 了吧,但你看看這些開發過 Chromium 的人最后還是放棄了 JavaScript,我們有理由相信他們是經過深思熟慮后做出的決定。按照 Google 工程師的話來說就是「我們關注包括 Web 技術在內的很多技術,我們取其精華并勇敢地扔掉歷史包袱?!?/p>
背后的故事2:在去年一年中,我們聽到的 Flutter 聲音更多是源自客戶端開發者,但自 1.0 發布后,吸引到了來自前端同學越來越多的關注。這一點和嚶嚶在「2019 前端技術規劃該包含什么?」中 回答 提到的現象類似。但前端同學有沒有想過,Flutter 起源于移動端,現有 Flutter 雖然來自曾經 Chromium 團隊,但整體對客戶端開發的友好度是要高于前端開發的,畢竟有一個平臺層插件擺在那里,再看看 Flutter 即將推出的 HummingBird,乍一看是 Web 的福音,但這也只是為 Flutter to Web 提供了途徑,而非為前端提供了增強 Web 的可能。從某種意義上說,Web 的疆土正在逐漸縮小。這一次,我們是否真的要失業了呢?
注:關于 Google 工程師的一段話描述意譯自 Google 工程師在 Flutter 圓桌會上的相關言論,有出入。