Flutter 是一套高效的跨平臺免費開源 SDK,可以幫助開發者用一套代碼同時在 Android 和 iOS 上構建媲美原生體驗的精良應用。隨著 Flutter 從 1.0 升級到 1.2,我們從社區中也蒐集到了不少開發者關注的問題,我們會用連載的形式由淺到深地為開發者們進行解答。如果您對 Flutter 已經有一定的瞭解,不妨在看到問題的時候先試著回答,然後和我們給出的答案進行比較,從而進一步加深理解。
問題 1:Flutter 是使用什麼技術構建的?
Flutter 使用 C、C++、Dart 和 Skia (2D 渲染引擎) 構建。您可以參閱下面這張架構圖。
問題 2:Flutter 如何在 Android 上運行我的代碼?
引擎的 C 和 C++ 代碼使用 Android 的 NDK 編譯。Dart 代碼 (SDK 的和您寫的) 都是預先 (ahead-of-time, AOT) 編譯成本地 ARM 及 x86 庫。這些庫被包含在一個 Android "runner" 項目中,然後整套內容被編譯成一個 APK。當應用啟動時,它會加載 Flutter 庫。任何渲染、輸入或事件處理等都會 delegate 給編譯好的 Flutter 和應用代碼。這個工作機制與很多遊戲引擎頗為相似。
調試模式時則使用虛擬機 (VM) 來運行 Dart 代碼(因此這時會顯示 "Debug" 字樣,以提醒開發者速度會稍微變慢),這樣便可以啟用有狀態熱重載 (Stateful Hot Reload)。
問題 3:Flutter 如何在 iOS 上運行我的代碼?
引擎的 C 和 C++ 代碼使用 LLVM 編譯。Dart 代碼 (SDK 的和您的) 都是預先 (ahead-of-time, AOT) 編譯成本地 ARM 庫。這些庫被包含在一個 iOS "runner" 項目中,然後整套內容被編譯成一個 .ipa。當應用啟動時,它會加載 Flutter 庫。任何渲染、輸入或事件處理等都會 delegate 給編譯好的 Flutter 和應用代碼。這個工作機制與很多遊戲引擎頗為相似。
調試模式時則使用虛擬機 (VM) 來運行 Dart 代碼 (因此這時會顯示 "Debug" 字樣,以提醒開發者速度會稍微變慢),這樣便可以啟用有狀態熱重載 (Stateful Hot Reload)。
問題 4:Flutter 是否會使用系統的 OEM widget?
不會。相反,Flutter 自己提供了一套 widget (包括 Material Design 和 iOS 風格的 Cupertino widget),由 Flutter 的框架和引擎負責管理和渲染。
- 瀏覽 Flutter widget 目錄
- https://flutter.dev/docs/development/ui/widgets
我們希望最終能夠產生出更高質量的應用。如果我們直接使用 OEM 自帶的 widget,那麼 Flutter 應用的質量和性能將受到這些 widget 質量的限制。
例如,在 Android 中,有一組硬編碼的手勢和固定的計算規則來區別它們。在 Flutter 中,您可以編寫自己的手勢識別器,它在手勢系統中擁有最高的優先級。此外,由不同人創作的兩個 widget 可以進行協調,以便消除手勢的歧義。
- 手勢系統
- https://flutter.dev/docs/development/ui/advanced/gestures
如今的應用設計趨勢表明,很多設計師和用戶都需要動效豐富的 UI,同時富有品牌表現力。為了實現這種級別的美學定製化設計,Flutter 在架構上就會傾向於直接驅動像素,而不是交給 OEM widget 來處理。
由於使用相同的渲染器、框架和 widget,就意味著您能更加輕鬆地同時發佈 iOS 和 Android 版本應用,而無需耗費精力和成本來規劃和同步兩套獨立的代碼庫和功能集。
另外,使用單一的語言、單個框架和同一組適用於所有 UI 的庫 (無論您的 UI 在每個移動平臺上都各有不同還是基本一致),也有助於幫助您降低應用開發和維護成本。
問題 5:我的移動 OS 更新並加入新的 widget 時會怎麼樣?
Flutter 團隊密切關注來自 iOS 和 Android 的 widget 使用和需求情況,且會與社區合作,對新的 widget 提供構建支持。這些支持可能會以這些形式來提供給開發者: 較低層級的框架功能、新的可編輯組合的 widget,或全新的 widget 實現。
Flutter 的分層架構旨在支持眾多 widget 庫,我們鼓勵並支持社區構建和維護 widget 庫。
問題 6:我的移動 OS 更新並加入新的平臺功能時會怎麼樣?
Flutter 的互操作 (interop) 和插件 (plugin) 系統旨在使開發者能夠立即訪問新的移動操作系統特性和功能。開發者不必等待 Flutter 團隊提供新系統功能的訪問接口,而是自己第一時間即可使用。
問題 7:我能使用哪些操作系統開發 Flutter 應用?
Flutter 支持使用 Linux、Mac 和 Windows 進行開發。
問題 8:Flutter 是用哪種語言寫成的?
我們對比了很多開發語言和運行時,並最終採用了 Dart 來編寫框架和 widget。底層圖形框架和 Dart 虛擬機在 C/C++ 中實現。
問題 9:Flutter 為什麼選擇使用 Dart?
Flutter 使用四個主要維度進行評估,並綜合考慮了框架開發者、應用開發者和最終用戶的需求。我們發現某些語言的確在某些維度符合要求,但 Dart 在所有評估維度上都取得了高分,並且符合我們的所有要求和標準。
Dart 的運行時和編譯器支持 Flutter 的兩個關鍵特性: 基於 JIT 的快速開發週期,允許在帶類型的語言中支持形變和有狀態熱重載,以及一個能產出高效率 ARM 代碼的 AOT 編譯器,從而確保快速啟動的能力和可預期的生產版本運行性能。
此外,我們還有幸與 Dart 社區展開了密切合作,Dart 社區積極投入資源改進 Dart,以便在 Flutter 中更易使用。例如,當我們採用 Dart 時,該語言還沒有用於生成原生二進制文件的 AOT 工具鏈,這些工具有助於實現穩定的高性能表現,但在 Dart 團隊為 Flutter 構建了這些工具後,這個缺失已經不復存在了。同樣,Dart VM 之前是針對吞吐量進行的優化,但團隊現在正在針對延遲進行優化,這對於解決 Flutter 的工作負載更為重要。
在評估時,Dart 在以下主要標準上得分很高:
開發者的生產力。Flutter 的主要價值之一就是讓開發者能使用相同的代碼庫為 iOS 和 Android 創建應用,以便節省開發資源。使用高效率的語言可以進一步提升開發者的工作效率,使 Flutter 更具吸引力。這對我們的框架開發團隊和最終開發者來說都非常重要。Flutter 的大部分內容所使用的語言都與我們為開發者提供的語言相同,因此我們需要在數十萬行的代碼中保持高效率,同時避免犧牲我們開發出來的框架和 widget 的親和力以及可讀性。
面向對象。對於 Flutter 而言,我們需要一種適合其問題域——創建可視化用戶體驗——的語言。這個領域中沉澱了數十年的面向對象構建 UI 框架的經驗。雖然我們可以使用非面嚮對象語言,但這意味著,為了解決幾個難題,我們要 "重新發明輪子"。此外,絕大多數開發者都擁有面向對象開發的經驗,因此可以更輕鬆地學習如何使用 Flutter 進行開發。
穩定可期的高性能表現。我們希望開發者能夠通過 Flutter 創建快速而流暢的用戶體驗。為了實現這一點,我們需要能夠在每個動畫幀期間運行大量的最終開發者代碼。這意味著我們需要的語言一方面既要擁有高性能,另一方面又需要避免因週期性的中斷而影響幀率,即 "可期性"。
快速內存分配。Flutter 框架使用的函數式流程,很大程度上依賴於下層的內存分配器高效地對小型的、短生命週期的內容進行內存分配。這個流程是使用支持這種分配機制的語言進行開發的,在缺少這個機制的語言中無法有效運作。
問題 10:Flutter 能運行任何 Dart 代碼嗎?
Flutter 應該能夠運行大多數沒有引用 dart:mirrors 或 dart:html (不論是直接還是間接引用) 的 Dart 代碼。
問題 11:Flutter 引擎有多大?
在 2018 年 12 月,我們實測了一個最簡版本的 Flutter 應用 (即不含 Material 組件,只包含一個使用 flutter build apk 構建的 Center widget) 的下載體積 ,這個經過打包和壓縮處理的 APK 大約為 4.06 MB。
- GitHub 上的最簡應用
- https://github.com/flutter/flutter/tree/75228a59dacc24f617272f7759677e242bbf74ec/examples/hello_world
對於這個最簡應用,核心引擎體積約為 2.7 MB (壓縮後),框架 + 應用代碼體積約為 820.6 KB (壓縮後),LICENSE 文件體積為 53.5 KB (壓縮後),必要的 Java 代碼 (classes.dex) 體積為 61.8 KB (壓縮後),並且有大約 450.4 KB的 ICU 數據 (壓縮後)。
這些數字是由 Android Studio 內置的 apkanalyzer 實測得出。
- apkanalyzer
- https://developer.android.google.cn/studio/command-line/apkanalyzer
在 iOS 平臺上,跟據 App Store Connect 的數據,同一應用的發佈 IPA 在 iPhone X 上的下載文件體積為 10.8 MB。IPA 比 APK 大,主要是因為 Apple 加密了 IPA 中的二進制文件,使得壓縮效率降低。
- iOS App Store Specific Considerations - 關於加密
- https://developer.apple.com/library/archive/qa/qa1795/_index.html#//apple_ref/doc/uid/DTS40014195-CH1-APP_STORE_CONSIDERATIONS
當然,您的實際情況可能跟我們所說的有所不同,我們建議您測量自己的應用的體積。想要測量 Android 應用體積,請運行 flutter build apk,並將 APK (build/app/outputs/apk/release/app-release.apk) 加載到 Android Studio 中,以便獲取詳細的體積報告。想要測量 iOS 應用,請將發佈 IPA 加載到 App Store Connect 並獲取體積報告。
- 使用 Android Studio 加載 APK(https://developer.android.google.cn/studio/build/apk-analyzer)
- 使用 App Store Connect 加載 IPA(https://flutter.dev/docs/deployment/ios)
原文鏈接:https://mp.weixin.qq.com/s/qXNbT-pJ4wnKANhUsyn2xw
閱讀更多 開發指南 的文章