【開發經驗】淺談flutter的優點與缺點
本文預設你已經是開發者,並對Flutter
有基本的瞭解,但是還未深入使用,希望瞭解Flutter
在商業級(而非demo)的專案中的優勢與劣勢。
很多前端開發者應該都尋找過跨平臺的App解決方案,包括沒有同時獨立開發iOS
和Android
雙端原生app的開發者,應該都接觸過或者看到過Google的Flutter
框架。我對於iOS原生開發與基於Vue.js的web開發比較熟悉,並在一個正在進行的藍芽硬體專案中應用了Flutter
框架,經歷的漫長的適應,在本文中我將以iOS原生開發者與web開發者的視角看待Flutter
框架,簡單羅列Flutter
的優勢與缺點。
Flutter優點
Flutter
的優點非常明顯,如果你選擇一個跨平臺框架,與眾多基於html
Flutter
絕對是體驗最好,效能與構建思路幾乎最接近原生開發的框架。
- 效能強大,流暢
Flutter
對比weex
和react native
相比,效能的強大是有目共睹的。基於dom
樹渲染原生元件,很難與直接在原生檢視上繪圖比肩效能,Google作為一個輪子大廠,直接在兩個平臺上重寫了各自的UIKit,對接到平臺底層,減少UI層的多層轉換,UI效能可以比肩原生,這個優勢在滑動和播放動畫時尤為明顯。
- 路由設計優秀
Flutter
的路由傳值非常方便,push
一個路由,會返回一個Future
物件(也就是Promise
物件),使用await
或者.then
就可以在目標路由pop
,回到當前頁面時收到返回值。這個反向傳值的設計基本是甩了微信小程式一條街了。彈出dialog
- 單例模式
Flutter
支援單例模式,單例模式的實現也非常簡單。單例模式很好的解決了一些問題。相比之下,js的單例則並不是一個真正的單例,或者說不是一個簡單的單例,這也是受限於js所執行的環境。單例模式並不總是合理的,容易被濫用。但是在App的初期開發中,往往一個容易實現的單例可以幫助我們快速完成一些邏輯的搭建。
- 優秀的動畫設計
Flutter
的動畫簡單到不可思議,動畫物件會根據螢幕重新整理率每秒產生很多個(一般是60個)浮點數,只需要將一個元件屬性通過補間(Tween)關聯到動畫物件上,Flutter
會確保在每一幀渲染正確的元件,從而形成連貫的動畫。這種十分暴力的操作在Flutter
Flutter
的一個魔力所在。相比之下其他跨平臺框架幾乎不能設計動畫……往往會遭遇非常嚴重的效能問題。
- UI跨平臺穩定
Google直接在兩個平臺上在底層重寫了UIKit,不依賴於Css
等外部直譯器,幾乎不存在UI表達不理想,渲染不正常的情況,可以獲得非常穩定的UI表達效果。Css
換個瀏覽器就有不同的表現,基於Css
的跨平臺框架很難獲得穩定的UI表現。
- 可選靜態的語言,語言特性優秀
Dart
是一個靜態語言,這也是相對於js的一個優勢。Dart
可以被編譯成js,但是看起來更像java
。靜態語言可以避免錯誤,獲得更多的編輯器提示詞,極大的增加可維護性。很多js庫也已經用ts重寫了,Vue3.0
的底層也將全部使用ts編寫,靜態語言的優勢不言而喻。
Flutter缺點
- 假裝是跨平臺,躲不開的原生平臺與原生程式碼
這是最大的問題,跨平臺框架說白了就是UI跨平臺,最後還是在原生平臺執行,本來兩個平臺就有天壤之別,一套程式碼就想吃掉iOS和Android在實際應用之中其實根本就不現實。Flutter
具有與原生程式碼互相呼叫的能力固然非常科學,但是問題反而顯得更加明顯——我一個前端工程師上哪裡去知道什麼是UIViewController
,什麼是Activity
呢?我要是雙端都熟悉,學習Flutter
就顯得很沒有必要。這是一個很矛盾的點,特別是在團隊裡,只有幾個前端突然想學Flutter
,是絕對做不來大專案的,如果有原生開發者,那就沒必要搞Flutter
了。
- 組合而不是繼承的思路
Flutter
提倡“組合”,而不是“繼承”。在iOS開發中,我們經常會繼承UIView,重寫UIView的某個生命週期函式,再新增一些方法和屬性,來完成一個自定義的View。但是在Flutter
中這些都是不可能的——屬性都是final
的,例如你繼承了了一個Container
,你是不能在它的生命週期中修改他的屬性的。你始終需要巢狀組合幾種Widget
,例如Row
,Container
,ListView
等Widget
。這種方法非常不符合直覺,初學時很難想明白如何構建一個完整的元件。
- Widget的型別難以選擇
Flutter
的Widget
分為StatefulWidget
和StatelessWidget
兩種,一種是帶狀態的一種是不帶狀態的,剛開發的時候很難想明白用哪個,因為StatelessWidget
也能存值,其實區別就在於框架重構UI的時候會使用State
來重構,如果是StatelessWidget
,暫時存進去的值就沒了。但是問題遠不止這麼簡單,好在只是有點麻煩,並不影響產品效能。
- 糟糕的UI控制元件API
雖然google儘可能的讓我們通過建構函式定製化Widget
,但是也難免有遺漏的。例如,又一次我想修改一個Appbar
的高度,居然沒有找到關於高度的屬性,通過閱讀原始碼發現,高度是寫死(const
)的。上文已經說過,無法通過生命週期來改變元件屬性,自己寫Appbar顯得非常沒必要,畢竟我還是想使用Appbar
的各種方便的功能。最後我只能把他的原始碼全部複製出來,直接修改高度來使用。初學框架,和一些初級開發者是不可能有迅速閱讀原始碼的能力的(作為框架也不應該產生如此問題)。一些定製化的UI的Api設計經常有缺失,好在我已經基本習慣了。除了Appbar
這種複雜的元件,自己寫一個小元件也並不費事。
- 糟糕的資源管理設計
這裡是最蠢的,Flutter
支援動態載入不同解析度的圖片,但是目錄設計太鬼畜了。簡單的說,Sketch匯出的多解析度資源,幾乎不可能直接拖到Flutter
裡用,極其,極其,麻煩。
- 牆
畢竟國情在此,要用Flutter
,先買梯子。雖然有“在中國使用Flutter”指南,但是太麻煩,沒梯子開發Flutter
,難度係數太高了,總不能碰到每個問題都花一整天尋找替代方案吧,先買好梯子圖個安心……
總結
Flutter
主要的坑就在於需要非常瞭解原生的環境,其實跨平臺的框架都是如此,想要通過跨平臺的API就拿下雙端的開發任務,對認真學習的原生開發者來說也是不公平的。
主要的優勢則在於動畫流暢,很多開發者反應比原生安卓還流暢(存疑),至少在iOS上是看不到卡頓的,安卓上動畫也很穩定,效能上展示了Google
的硬實力
本人是iOS原生開發者,亦熟悉Vue.js
,小程式等前端開發,對Android
開發與Reactive Naive
不甚瞭解,本文乃是一些初級經驗與感悟,若有不當還請評論指正。