Contents

常見問題與解答

Contents

簡介

本頁面收集了關於 Flutter 一些大家常見問題的解答。你可能還會想要檢視下面一些特別的答疑:

什麼是 Flutter?

Flutter 是 Google 的行動式 UI 工具套件,幫助你在移動、web、桌面端創造高品質的絕妙原生體驗的應用。 Flutter 可以和世界上的開發人員和開發組織廣泛使用的那些現存程式碼一起使用,並且是開源的、免費的。

哪些人會用到 Flutter?

對於使用者來說,Flutter 將美妙的應用帶到了生活中。

對於開發者來說,Flutter 降低了應用開發的入門門檻。它加速了應用開發的過程,減少了跨平臺開發的成本以及複雜度。

對於設計師來說,Flutter 提供了一個能夠實現高保真度使用者體驗的畫布。 Fast 公司評價 Flutter 是 一個設計靈感的源泉,提供了將概念轉換為生產程式碼的能力,卻沒有典型的框架強加的妥協。 Flutter 同時也是一個能提高生產力的原型工具,可以透過 CodePen 與他人分享你的創意。

對於工程主管以及僱主來說,Flutter 可以將不同平台的應用開發者,統一為一個 移動端、前端和桌面端應用程式 的團隊,共同建立品牌,並在單個程式碼庫中打造的多個平台的應用程式。 Flutter 加速了跨平臺下開發以及同步釋出處理序的開發進度。

我需要擁有怎樣的開發經驗才能使用 Flutter?

如果您熟悉面向物件概念 (類、方法、變數等) 和指令式程式設計概念 (迴圈、條件等) ,您會發現 Flutter 很容易上手。

就我們親歷過的例子來說,程式設計經驗並不豐富的人們一樣可以學習並使用 Flutter 進行原型設計和應用開發。

我可以用 Flutter 建構怎樣的應用?

Flutter 設計為了讓移動應用能夠執行在 Android 與 iOS,以及在 web 和桌面端執行可互動式的應用。

如果您的應用強烈需要表達出品牌個性,Flutter 會非常適合。不過,即便您想要打造的應用看起來像是股票平台那樣複雜,也可以使用 Flutter 來建構。

Flutter 的 軟體包生態 支援絕大多數硬體(包括攝影頭、GPS、網路以及儲存)以及服務(例如支付、雲儲存、驗證以及 廣告)。

Flutter 可以建構功能齊全的應用,包括使用攝影頭、地理位置、網路、儲存、第三方 SDK 等。

誰創造了 Flutter?

Flutter 是一個開源專案,由 Google 和開發社群共同創造。

誰在使用 Flutter?

Google 內部和外部的開發者使用 Flutter 為 Android 和 iOS 建構精美的原生應用。您可以存取 案例頁面 來了解一些知名的開發者 / 組織。

Flutter 有哪些獨到之處?

Flutter 與大多數用來建構移動應用的工具不同,因為它既不使用 WebView,也不使用裝置附帶的 OEM Widget,而是使用自己的高效能渲染引擎來繪製 Widget。

Flutter 與其它工具的不同之處還在於,它只有一層簡潔的 C/C++ 程式碼,在這之上,Flutter 使用 Dart (一種現代化的、簡潔的面嚮物件語言) 實現其大部分系統功能 (佈局、手勢、動畫、框架、Widget 等),這種語言使得開發者可以輕鬆地進行閱讀、更改、替換或刪除。這些特性都為開發者提供了巨大的系統控制權限,同時顯著降低了存取大多數系統功能的門檻。

我需要使用 Flutter 來建構我的下一個應用嗎?

Flutter 1.0 已於 2018 年 12 月推出, Flutter 2 在 2021 年 3 月 3 日釋出。至今為止,成千上萬使用了 Flutter 的應用已經被安裝到了數億台裝置中。請透過成功 案例頁面 瞭解知名開發者們的成果。

Flutter 進行了高品質的持續交付更新,優化了穩定性、效能以及一些常見的使用者需求。

Flutter 能夠為我們提供什麼?

Flutter SDK 裡有什麼?

Flutter 包括了:

  • 高度最佳化的針對移動應用的 2D 渲染引擎,更具備出色的文字支援功能

  • 現代化的 react 風格框架

  • 豐富的 widgets,很好的實現了 Material Design 風格及 iOS 風格。

  • 用於單元和整合測試的 API

  • 用於連線系統和第三方 SDK 的互操作及外掛 API

  • 無介面 (headless) 測試執行器,用於在 Windows、Linux 和 Mac 上執行測試

  • Dart DevTools 用以測試、除錯和分析你的應用

  • 命令列工具,用於建立、建構、測試和編譯應用

用 Flutter 開發時可以使用哪些編輯器或 IDE?

可以透過外掛的方式使用 Android StudioIntelliJ IDEAVS Code 開發 Flutter 應用。請參閱 邊界配置 以瞭解如何初始化,以及 Android Studio/IntelliJVS Code 如何使用 plugin 的小提示。

有關設定的詳細資訊,請參閱 編輯器配置文件,以及使用 Android Studio/IntelliJVS Code 外掛的小提示。

您也可以在命令列中使用 flutter 命令,並配合能編輯 Dart 語言的編輯器 進行開發。

Flutter 裡存在開發框架嗎?

是的,Flutter 自帶了現代化的開發框架,靈感正是來自 React。 Flutter 的框架旨在實現分層、可客製 (以及靈活的開發選項)。開發者可以選擇僅使用框架的一部分,或是使用另外的框架。

Flutter 裡存在 Widget 嗎?

是的,Flutter 自帶了一套 高品質的 Material Design 和 Cupertino (iOS 風格) Widget、佈局和主題。當然,這些 Widget 只是一個起點。 Flutter 的設計目的就是,讓您輕鬆建立自己的 Widget,或是客製現有的 Widget。

Flutter 支援 Material Design 嗎?

是的,Flutter 和 Material 團隊密切合作,完全支援 Material Theming。你可以透過 codelab 瞭解 Material 元件 (MDC) 主題客製: MDC-103 Flutter: Material Theming

Flutter 帶有測試框架嗎?

是的,Flutter 提供用於編寫單元和整合測試的 API。瞭解更多有關 Flutter 測試的資訊請檢視 測試 Flutter 應用

我們使用自己的測試功能來測試我們的 SDK,每次提交程式碼前我們都會測量提交的 測試覆蓋率

Flutter 是否附帶除錯工具?

Flutter 本身附帶了 除錯工具(也稱為 Dart DevTools)。你可以在 除錯 FlutterFlutter DevTools 文件中瞭解更多資訊。

Flutter 是否帶有依賴注入 (dependency injection) 的框架?

我們並沒有提供相關解決方案,但是這裡有許多套件提供了依賴注入或服務定位的能力,例如 injectableget_itkiwiriverpod

技術篇

Flutter 是使用什麼技術建構的?

Flutter 使用 C、C++、Dart 和 Skia (2D 渲染引擎) 建構。您可以參閱下面這張 架構圖 來理解其主要建構。若您需要了解 Flutter 的分層架構,請閱讀 架構概覽

Flutter 如何在 Android 上執行我的程式碼?

引擎的 C 和 C++ 程式碼使用 Android 的 NDK 編譯。 Dart 程式碼 (SDK 的和您寫的) 都是預先 (ahead-of-time, AOT) 編譯成本地 ARM 及 x86 庫。這些庫被包含在一個 Android “runner” 專案中,然後整套內容被編譯成一個 APK。當應用啟動時,它會載入 Flutter 庫。任何渲染、輸入或事件處理等都會 delegate 給編譯好的 Flutter 和應用程式碼。這個工作機制與很多遊戲引擎頗為相似。

除錯模式時,Flutter 使用虛擬機器 (VM) 來執行 Dart 程式碼(因此這時會顯示 “Debug” 字樣,以提醒開發者速度會稍微變慢),這樣便可以啟用有狀態熱重載 (Stateful Hot Reload),它能夠讓你無需重新編譯整個應用就能看到程式碼變更帶來的變化。當執行該模式時,你可以看到一個 “debug” banner 在你應用的右上角。請記住,這時的效能並不是最終釋出應用時的效能。

Flutter 如何在 iOS 上執行我的程式碼?{#run-ios}

引擎的 C 和 C++ 程式碼使用 LLVM 編譯。Dart 程式碼 (SDK 的和您的) 都是預先 (ahead-of-time, AOT) 編譯成本地 ARM 庫。這些庫被包含在一個 iOS “runner” 專案中,然後整套內容被編譯成一個 .ipa。當應用啟動時,它會載入 Flutter 庫。任何渲染、輸入或事件處理等都會代理給編譯好的 Flutter 和應用程式碼。這個工作機制與很多遊戲引擎頗為相似。

Flutter 是否會使用作業系統內建的 widget?

不會。相反,Flutter 自己提供了一套 widget (包括 Material Design 和 iOS 風格的 Cupertino widget),由 Flutter 的框架和引擎負責管理和渲染。你可以在這裡瀏覽 Flutter widget 目錄

我們希望最終能夠產生出更高品質的應用。如果我們直接使用 OEM 自帶的 widget,那麼 Flutter 應用的品質和效能將受到這些 widget 品質的限制。

例如,在 Android 中,有一組硬編碼的手勢和固定的計算規則來區別它們。在 Flutter 中,您可以編寫自己的手勢識別器,它在 手勢系統 中擁有最高的優先順序。此外,由不同人創作的兩個 widget 可以進行協調,以便消除手勢的歧義。

如今的應用設計趨勢表明,很多設計師和使用者都需要動效豐富的 UI,同時富有品牌表現力。為了實現這種級別的美學客製化設計,Flutter 在架構上就會傾向於直接驅動畫素,而不是交給 OEM widget 來處理。

由於使用相同的渲染器、框架和 widget,就意味著您能更加輕鬆地同時釋出 iOS 和 Android 版本應用,而無需耗費精力和成本來規劃和同步兩套獨立的程式碼庫和功能集。

另外,使用單一的語言、單個框架和同一組適用於所有 UI 的函式庫(無論您的 UI 在每個移動平臺上都各有不同還是基本一致),也有助於幫助您降低應用開發和維護成本。

我的移動 OS 更新並加入新的 widget 時會怎麼樣?

Flutter 團隊密切關注來自 iOS 和 Android 的 widget 使用和需求情況,且會與社群合作,對新的 widget 提供建構支援。這些支援可能會以這些形式來提供給開發者: 較低層級的框架功能、新的可編輯組合的 widget,或全新的 widget 實現。

Flutter 的分層架構旨在支援眾多 widget 庫,我們鼓勵並支援社群建構和維護 widget 庫。

我的移動 OS 更新並加入新的平台功能時會怎麼樣?

Flutter 的互操作 (interop) 和外掛 (plugin) 系統旨在使開發者能夠立即存取新的移動作業系統特性和功能。開發者不必等待 Flutter 團隊提供新系統功能的存取介面,而是自己第一時間即可使用。

我能使用哪些作業系統開發 Flutter 應用?

Flutter 支援使用 Linux、Mac 和 Windows 進行開發。

Flutter 是用哪種語言寫成的?

Dart 是一個現代化高度發展,併為終端應用專門最佳化的語言。底層圖形框架和 Dart 虛擬機器在 C/C++ 中實現。

Flutter 為什麼選擇使用 Dart?

在最初的開發階段,Flutter 團隊調研了很多開發語言和執行時,最終在框架和小部件中採用了 Dart。 Flutter 主要基於四個維度進行評估,並同時考慮了框架作者、開發人員和終端使用者的需求。我們發現許多語言都滿足了一些要求,但 Dart 在我們所有的評估維度上都獲得了高分,並且滿足了我們的所有要求和標準。

Dart 執行時和編譯器支援 Flutter 的兩個關鍵功能的組合:基於 JIT 的高效開發,允許在具有型別的語言中進行形參更改,以及保持狀態的熱重載;還有 AOT 編譯器,可產出高效的 ARM 程式碼,為生產部署帶來快速啟動和可觀的效能。

此外,我們還有幸與 Dart 社群展開了密切合作,Dart 社群積極投入資源改進 Dart,以便在 Flutter 中更易使用。例如,當我們採用 Dart 時,該語言還沒有用於產生原生二進位制檔案的 AOT 工具鏈,這些工具有助於實現穩定的高效能表現,但在 Dart 團隊為 Flutter 建構了這些工具後,這個缺失已經不復存在了。同樣,Dart VM 之前是針對吞吐量進行的最佳化,但團隊現在正在針對延遲進行最佳化,這對於解決 Flutter 的工作負載更為重要。

在評估時,Dart 在以下主要標準上得分很高:

開發人員生產力
Flutter 的主要價值之一,是透過讓開發人員用同一套程式碼,建立適用於 iOS 和 Android 的應用而節省開發資源。使用高生產力的語言加速開發,並提升 Flutter 的吸引力。這對於我們的框架團隊和開發人員都很重要。 Flutter 本身的大部分內容所用的語言都和我們提供給使用者的一樣,所以我們要讓十萬行程式碼保持生產力,而不會犧牲框架和部件對我們開發人員的可達性和可讀性。

面向物件
對於 Flutter 而言,我們需要一種適合建立視覺化使用者體驗的語言。這個領域中沉澱了數十年的面向物件建構 UI 框架的經驗。雖然我們可以使用非面嚮物件語言,但這意味著,為了解決幾個難題,我們要 “重新發明輪子”。此外,絕大多數開發者都擁有面向物件開發的經驗,因此可以更輕鬆地學習如何使用 Flutter 進行開發。

穩定可期的高效能表現
我們希望開發者能夠透過 Flutter 建立快速而流暢的使用者體驗。為了實現這一點,我們需要能夠在每個動畫幀期間執行大量的最終開發者程式碼。這意味著我們需要的語言一方面既要擁有高效能,另一方面又需要避免因週期性的中斷而影響幀率,即 “可期性”。

快速記憶體分配
Flutter 框架使用的函式式流程,很大程度上依賴於下層的記憶體分配器高效地對小型的、短生命週期的內容進行記憶體分配。這個流程是使用支援這種分配機制的語言進行開發的,在缺少這個機制的語言中無法有效運作。

Flutter 可以執行那些沒有直接或間接匯入了 dart:mirrorsdart:html 的函式庫。

Flutter 引擎有多大?

2021 年 3 月,我們實測了一個 最簡版本的 Flutter 應用 (即不含 Material 元件,只包含一個使用 flutter build apk --split-per-abi 建構的 Center widget 的 app)壓縮且 Bundle 一個 release 的 APK, ARM64 下是 4.6 MB,ARM32 下是 4.3 MB。

在 ARM32 下,核心的引擎大約佔 3.4 MB,框架和應用的程式碼大約是 765 KB,許可證檔案大約是 58 KB,必要的 Java 程式碼(classes.dex)是 120 KB。上述資料均為經過壓縮處理之後的大小。

在 ARM64 下,核心的引擎大約佔 4.0 MB,框架和應用的程式碼大約是 659 KB,許可證檔案大約是 58 KB,必要的 Java 程式碼(classes.dex)是 120 KB。上述資料均為經過壓縮處理之後的大小。

這些數字是由 AndroidStudio 內建的 apkanalyzer 實測得出。

«««< HEAD 在 iOS 平臺上,跟據 App Store Connect 的資料,同一應用的釋出 IPA 在 iPhone X 上的下載檔案體積為 10.9 MB。 IPA 比 APK 大,主要是因為 Apple 加密了 IPA 中的二進位制檔案,使得壓縮效率降低。(可以檢視 iOS App Store Specific ConsiderationsQA1795 關於加密的部分)

The release engine binary includes LLVM IR (bitcode). Xcode uses this bitcode to produce a final binary for the App Store containing the latest compiler optimizations and features. The profile and debug frameworks contain only a bitcode marker, and are more representative of the engine’s actual binary size. Whether you ship with bitcode or not, the increased size of the release framework is stripped out during the final steps of the build. These steps happen after archiving your app and shipping it to the store. Note bitcode has been deprecated and will be removed from Flutter in a future release. =======

4dbd3b8b2010ddec7bcd30bd25c61ed53d338446

Release 模式下引擎二進位制產物將包含 LLVM 的中間語言表示 (bitcode)。 Xcode 將使用 bitcode 為 App Store 產生最終包含了最新的編譯器最佳化和功能的二進位制檔案。 Profile 和 Debug 模式下的 Framework 中, bitcode 部分僅包含 bitcode marker,因此更能代表引擎的真實大小。無論你是否使用 bitcode, release 模式下增加的包大小都會在應用歸檔且釋出到應用商店後,在建構的最終步驟裡被移除。請注意 bitcode 已經被廢棄,並即將在未來的 Flutter 正式版本中被移除。

當然,您的實際情況可能跟我們所說的有所不同,我們建議您測量自己的應用的體積。想要測量應用體積,請檢視 測量你的應用體積

賦能

Flutter 應用會擁有怎樣的效能表現?

Flutter 應用會有很出色的效能。 Flutter 設計的目標就是幫助開發者輕鬆實現 60fps 的穩定幀率。 Flutter 應用透過本地編譯的程式碼執行——不涉及解釋過程。這也意味著 Flutter 應用啟動會非常快捷。

開發 Flutter 時的操作週期有多長?修改程式碼和看到介面內容更新之間會隔多久?

Flutter 使用的是熱重載式的開發操作週期。您在實機或者模擬器上都能實現亞秒級的修改和更新速度。

另外,Flutter 的熱重載是有狀態的 (stateful),這意味著重新載入後 app 的狀態會被保留。這樣即使您修改的介面在應用很深的位置,重載後您也能直接看到修改後的該介面,而無需從應用首頁開始重新操作。

熱重載 hot reload 相比較熱重啟 hot restart 的區別在哪裡?

透過將更新的原始碼檔案注入到正在執行的 Dart VM(虛擬機器)中來進行熱重載。這不僅會新增新的類,還會向現有的類中新增方法和欄位,並更改現有的函式。熱重啟後會將狀態重置為應用程式的初始狀態。

更多關於熱重載的詳細資訊,請檢視文件:使用熱重載

我能把 Flutter 應用部署到哪裡?

您可以將 Flutter 應用編譯並部署到 iOS 和 Android 平台,亦可部署到 web 平台以及 桌面端

Flutter 可以執行在哪些裝置,哪些作業系統版本上?

  • 我們會為各種從低端到高階的平台進行支援並且加入測試。您可以檢視 已支援的平台 以瞭解已測試的平台列表。

  • Flutter 支援在 x86_64armeabi-v7aarm64-v8a 架構下建構為 ahead-of-time (AOT) 庫。

  • 為 ARMv7 或 ARM64 建構的應用在很多 x86 Android 裝置上執行良好 (使用 ARM 模擬器)。

  • 我們支援在不同的平臺上開發 Flutter 應用,請參閱 不同作業系統下安裝 Flutter 的方法文件 瞭解更多。

Flutter 能在 Web 上執行嗎?

可以的,目前 stable channel 已經支援 web 平台了。你可以將已有的 Flutter 程式碼編譯在 web 執行。更多詳細資訊,請參閱 Web 介紹

我能使用 Flutter 建構桌面應用嗎?

可以,Flutter 的桌面端穩定版支援已經適用於 Windows、macOS 和 Linux 啦。

我能在我現有的原生應用裡使用 Flutter 嗎?

是的,你可以在我們網上內的 混合應用 章節中學習。同時,請留意新增 多個 Flutter 頁面或 view 體驗版已經上線了。

請參考 這個文件,檢視如何將 Flutter 加入現有的專案。

我能存取感測器、本地儲存之類別的平台服務和 API 嗎?

可以。Flutter 預設即為開發者提供了作業系統中 一些 平台專屬服務和 API 的操作入口。但是,我們希望避免大多數跨平臺 API 的“最小公約數”問題,因此我們不打算為所有本地服務和 API 建構跨平臺的操作 API。

很多平臺服務和 API 都在 Pub 站點中提供了 現成的程式碼包,我們可以根據 說明 使用它們,非常方便。

最後,我們鼓勵開發者使用 Flutter 的非同步訊息傳遞系統來創建出 自己的平台 與第三方 API 的整合方案。開發者可以根據需要公開儘可能多 (或者儘可能少) 的平台 API,並建構最適合其專案的抽象層。

我能對自帶的 widget 進行擴充和客製嗎?

當然可以。Flutter widget 系統的設計思路就是讓開發者可以輕鬆客製。

Flutter 沒有讓每個 widget 都提供大量引數,而是採用了組合的方式。較大的 widget 是用較小的 widget 組合構建出來的,您可以重複使用它們,並以新穎的方式對其加以組合,從而產生自訂的 widget。例如,RaisedButton 沒有繼承自一個通用按鈕 widget,而是將 Material widget 與 GestureDetector widget 組合在一起。 Material widget 負責視覺呈現,GestureDetector widget 則實現其互動。

如果您想要建立自訂設計的按鈕,可以將負責視覺呈現的 widget 與提供互動的 GestureDetector 組合起來使用。例如,CupertinoButton 就採用了這種方法,將 GestureDetector 與其他幾個負責表現視覺的 widget 進行組合。

這種組合策略使您可以最大限度地控制 widget 的視覺化和互動邏輯,同時重複利用大量程式碼。在框架中,我們將複雜的 widget 分解為實現視覺、互動和動效的各部分。您可以按照自己喜歡的方式重新組合這些 widget,從而製作出自訂 widget 來完整傳達出您的設計意圖。

我為什麼要在 iOS 和 Android 應用間共享佈局程式碼?

您可以選擇為 iOS 和 Android 應用實現不同的佈局。開發者可以在執行時期檢查移動作業系統的種類,並根據作業系統呈現不同的佈局,但我們發現這種做法比較少見。

我們發現移動應用佈局和設計正在不斷髮展,更趨於品牌設計的訴求,而且跨平臺之間的呈現逐漸趨同。這意味著不少開發者會有很強的動力在 iOS 和 Android 上共享佈局和 UI 程式碼。

如今,在應用美學設計中,品牌表達和客製比嚴格遵循平台自己的美學更為重要。例如,應用設計通常需要自訂字型、顏色、形狀、動效等,以便清楚地傳達出其品牌獨有的特性。

我們還發現,很多應用都在 iOS 和 Android 上採用了通用的佈局模式。例如,您現在可以在 iOS 和 Android 上很方便地找到“底部導航”設計模式。移動平臺上的設計理念似乎正在趨於一致。

我能與移動平臺上的預設程式語言進行互操作嗎?

可以,Flutter 支援呼叫 (包括整合) Android 上的 Java 或者 Kotlin 程式碼,或者 iOS 上的 ObjectiveC 或 Swift 程式碼。這是透過靈活的訊息傳遞方式實現的, Flutter 應用可以使用 BasicMessageChannel 向移動平臺收發訊息。

如果你想了解有關平台通道的更多資訊,可以查閱 platform channels 相關文件。

你也可以透過這個 範例專案,學習如何使用平台通道存取 iOS 和 Android 上的電池狀態資訊。

Flutter 包含反射 / 映象系統嗎?

不支援,Dart 的確是含有 dart:mirrors 庫,能夠提供型別反射。但是由於 Flutter 應用已經針對最終產物進行了預編譯,並且控制二進位制內容體積始終是現代移動應用需要面對的一個問題,所以我們禁用了 dart:mirrors。

使用靜態型別分析系統,我們可以移除任何不會用到的東西(”得益於 tree shaking 機制”)。如果你匯入了一個巨大的 Dart 庫,但僅僅用到了一個其中實現的一個兩行的函式,那麼你只需要付出這兩行函式的代價,即便是這個 Dart 庫中匯入了非常多非常多的函式庫。此保證僅 Dart 可以在編譯期安全識別程式碼路徑的情況下。目前,我們已找到其他滿足特定需求的方法以提供更好的平衡,如程式碼產生器。

我應該如何在 Flutter 實現國際化 (internationalization, i18n)、本地化 (localization, l10n) 和可及性 (accessibility, a11y) ?

關於國際化和本地化,請檢視課程: Flutter 應用裡的國際化

關於可及性 / 無障礙使用,請檢視文件:無障礙

我如何為 Flutter 開發並行 (parallel) 和/或併發 (concurrent) 應用?

Flutter 支援 isolate,一個個的 isolate 是 Flutter VM 裡彼此獨立的堆 (heap),可以並行執行 (通常以獨立執行緒的形式實現)。 Isolate 之間透過非同步收發訊息來進行通訊。

你可以點選連結檢視 在 Flutter 中使用 isolate 的範例

我能在 Flutter 應用後臺執行 Dart 程式碼嗎?

可以,你可以在 iOS 和 Android 後臺處理序中執行 Dart 程式碼。有關更多資訊,你可以檢視在 Medium 上的文章: 使用 Flutter 外掛和 Geofencing 在後台執行 Dart 程式碼

我在 Flutter 裡能使用 JSON/XML/protobuffers 等內容嗎?

當然可以。Pub 站點 提供了很多這樣的程式碼庫,包括 JSON, XML, protobufs 以及很多其他內容格式。

有關在 Flutter 中使用 JSON 的詳細介紹,你可以檢視 使用 JSON 的課程

我能用 Flutter 建構 3D (OpenGL) 應用嗎?

我們暫不支援透過 OpenGL ES 或類似的機制實現 3D。在 3D API 方面我們有一個長期的計劃,但目前我們專注於呈現 2D。

我的 APK 或 IPA 為什麼這麼大?

通常,影象、聲音檔案、字型等資源在 APK 或 IPA 裡佔據了相當的比重。 Android 和 iOS 生態系統中有很多工具可以幫助您瞭解 APK 或 IPA 中的各種內容的比重情況。

此外,請務必使用 Flutter 工具建立 APK 或 IPA 的_釋出版本_。釋出版本的體積通常_遠_小於_除錯_版本。

如果你想學習更多有關如何釋出版本的課程,可以檢視 打套件和釋出到 Android 平台 以及 打套件和釋出到 iOS 平台。同時,檢視 測量你的應用體積

Flutter 應用能在 Chromebook 上執行嗎?

我們注意到已經有 Flutter 應用執行在某些 Chromebook 上了。針對在 Chromebook 上執行 Flutter 的情況,我們有進行持續的追蹤,你可以檢視 Flutter 執行在 Chromebook 上的問題追蹤 來獲得相關資訊。

Is Flutter ABI compatible?

Flutter 和 Dart 尚未提供且目前不會提供應用二進位制介面 (ABI) 的支援。

框架

為什麼 build() 方法被放在 State 上,而不是 StatefulWidget 上?

將 Widget 的 build(BuildContext context) 方法放在 State 上,而不是將 Widget build(BuildContext context, State state) 方法放在 StatefulWidget 上,這個策略能讓開發者在繼承 StatefulWidget 時提供更多的靈活性,你可以在 API 文件中檢視 關於 State.build 的討論

Flutter 怎麼沒有標記語言 (markup language) 和語法?

Flutter 的 UI 由指令式的面嚮物件語言建構,也就是 Dart。它也是 Flutter 框架的編寫語言。Flutter 本身並不包含宣告式的標記語言。

我們發現將 UI 交給程式碼來動態建構會帶來更多的靈活性。比如,我們發現固化的標記語言系統很難表達一個從視覺到行為都完全客製的 widget。

另外,“程式碼優先”的開發也使得熱重載以及動態環境適配等特效能更好地得以實現。

從根本上來講,創造出一種能動態轉化成 widget 的語言是可能的,畢竟建構方法說到底也還是程式碼,他們能做的事情很多,自然也包括將標記語言轉化成 widget。

我的應用執行時在右上角有一個 Debug 的標識,為什麼?

預設情況下,flutter run 指令會使用 debug 編譯配置。

Debug 編譯配置會在一個 VM (Virtual Machine) 裡執行您的 Dart 程式碼,從而提供更快速的開發操作週期,如 熱重載。(如果是編譯釋出版本的話,則會使用 AndroidiOS 標準的工具鏈。)

Debug 編譯配置也會檢查所有的斷言 (assert),這會幫助您在開發時更早地發現錯誤,但這也會加大執行時的開銷。您看到的 Debug 標識是告訴您這些檢查目前是開啟的狀態。您可以透過在執行 flutter run 時附加 --profile 或者 --release 來跳過這些檢查。

如果您在使用 Flutter 的 IntelliJ 外掛,您可以在 profile 或者 release 模式下啟動應用,只需要在選單裡選擇 Run > Flutter run in Profile Mode 或者 Release Mode 即可。

Flutter 框架採用了哪些程式設計正規化?

Flutter 是一個多正規化的程式設計環境。過去幾十年中許多程式設計技術都有在 Flutter 中使用。我們在選擇正規化時會考慮其適用性進行綜合性的決策。以下列出的正規化不分先後:

組合 (composition)
這也是 Flutter 的主要開發正規化,將簡單的、行為有限的小物件進行組合,從而實現更復雜的效果。絕大多數 Flutter widget 都是用這種方法建構的。比如 Material TextButton 類是基於 MaterialButton 類建構的,而這個類則是由 IconThemeInkWellPaddingCenterMaterialAnimatedDefaultTextStyle 以及 ConstrainedBox 組合而成的。而 InkWell 則是由 GestureDetector 組成, Material 則是由 AnimatedDefaultTextStyleNotificationListenerAnimatedPhysicalModel 組成。如此等等。

函數語言程式設計 (functional programming)
整個應用都可以只用 StatelessWidget 來建構,它本質上就是一些方法,用來描述如何將引數傳送給其他方法,以及在佈局區域內計算佈局以及繪製圖像。當然這樣的應用一般也不會包含狀態,所以通常也無法進行互動。比如,Icon widget 就只是一個將其元素(顏色圖示尺寸)羅列在佈局區域內的方法。另外,當這個正規化被重度使用時,則會使用不可變的資料結構,如整個 Widget 類及其派生,以及一些輔助類,如 RectTextStyle。另外,從一個較小的尺度來看的話, Dart 的 Iterable API 也重度使用了這個正規化 (如 map, reduce, where 等方法),它在框架中經常被用來處理一系列的值。

事件驅動程式設計 (event-driven programming)
使用者的互動操作被包裝成事件物件,這些物件傳送給被各個 event handler 註冊的回呼(Callback)方法。螢幕內容的更新使用的也是類似的回呼(Callback)機制。比如,做為動畫系統建構基礎的 Listenable 類,就採用了包含多個事件監聽者的訂閱模型。

面向類程式設計 (class-based programming,是面向物件程式設計的一種方式)
框架內絕大多數的 API 是由包含各種繼承關係的類來組成的。我們在基本類中定義較高級別的 API,然後在其子類別中對這些 API 進行特化處理。比如,我們的渲染物件就有一個基本類 RenderObject),它對座標系的細節並不關心,但它的子類別 RenderBox) 就引入了笛卡爾座標系的概念(x/y座標值,以及寬度高度的概念)。

原型程式設計 (prototype-based programming,同樣是面向物件程式設計的一種方式)
ScrollPhysics 類在執行時動態連結那些會組成滾動邏輯的例項。這就使得系統無需在編譯時提前選擇平台的情況下,也能組合出符合平台特性的頁面滾動效果。

指令式程式設計 (imperative programming)
簡單直白的指令式程式設計,通常和物件內封裝的狀態 (state) 搭配使用,這種正規化能提供最符合直覺的解法。比如,測試就是使用指令式程式設計實現的,首先描述出測試的環境,然後給出測試需要滿足的定量,最後開始步進,或者根據測試需要插入事件。

響應式程式設計 (reactive programming)
Widget 和元素樹有時候被描述為響應式的,因為隨 widget 構造方法引入的新輸入會隨著其 build 方法傳播給更低等級的 widget;而底層 widget 中出現的修改 (如響應使用者的輸入) 也會沿著結構樹透過 event handler 向上傳播。在整個框架中,函式-響應式以及指令-響應式的實現都有出現,具體取決於 widget 的功能需求。 Widget 的 build 方法如果只是包含其針對變化如何響應的表示式的話,就是函式-響應式 widget (如 Material Divider 類)。如果 widget 的 build 方法包含一系列構造子元素的表示式,用於描述該 widget 如何響應變化的話,那它就是指令響應式 widget (如 Chip 類)。

宣告式程式設計 (declarative programming)
Widget 的 build 方法通常都是一個單一表達式,它包含多級巢狀(Nesting)的建構函式,且使用 Dart 嚴格的宣告式子集編寫。這些巢狀(Nesting)的表示式可以與合適的標記語言互相轉換。比如,UserAccountsDrawerHeader 這個 widget 就有一個很長的 build 方法 (20 多行),由一個巢狀(Nesting)的表示式構成。這種正規化也可以和指令式混合使用,以實現某些很難用純宣告式的方法實現的 UI。

泛型程式設計 (generic programming)
型別可以幫助開發者更早地抓到錯誤,基於這一點,Flutter 框架也採用了泛型開發。比如,State 類就是如此,其關聯的 widget 就是類別型引數,如此一來 Dart 分析器就能捕獲到 state 和 widget 不匹配的情況。類似的,GlobalKey 類就接受一個類別型引數,從而型別安全地存取一個 widget 的 state (會使用執行時期檢查)。 Route 介面也在被 popped 時接受型別引數,另外 List, Map, Set 這些集合也都如此,這樣就可以在分析或者執行時儘早發現型別不匹配的錯誤。

併發 (concurrent programming)
Flutter 大量使用諸如 Future 等非同步 API。比如,動畫系統就會在動畫執行完 future 時進行事件告知。同樣的,圖片載入系統也會使用 future 在載入完畢時進行告知。

約束程式設計 (constraint programming)
Flutter 的佈局系統使用了約束程式設計的簡化形態來描述一個場景的幾何性質。約束值 (比如一個笛卡爾矩形允許的最大 / 最小寬高值) 會從父元素傳遞給子元素,子元素最終選擇一個能滿足上面所有約束條件的最終尺寸。這種做法也使得 Flutter 能不依賴太多輸入的情況下快速完成一個全新的佈局。

工程管理

我該如何獲得技術支援?

If you think you’ve encountered a bug, file it in our issue tracker. You might also use Stack Overflow for “HOWTO” type questions. For discussions, join our mailing list at flutter-dev@googlegroups.com or seek us out on Discord.

如果您覺得遇到 bug 了,請提交至我們的 問題追蹤入口。我們也鼓勵您在 Stack Overflow 中多多使用 “如何 (how to) …“來搜尋解答。如果您希望直接與我們溝通,請使用我們的官方郵件地址 flutter-dev@googlegroups.com 或在 Discord 上向我們提問。

我如何投入到 Flutter 開發社群?

Flutter 是開源的,我們鼓勵您為此做出自己的貢獻。您可以透過 問題追蹤入口 來提交功能需求或者 bug 報告。

我們也希望您加入我們的郵件討論 flutter-dev@googlegroups.com,告訴我們您是如何使用 Flutter 的,以及打算用 Flutter 開發什麼。

如果您打算為 Flutter 貢獻程式碼,請先閱讀 程式碼貢獻指南,然後從 簡單待修復問題 列表中尋找力所能及的問題開始入手。

最後,您可以與各個 Flutter 社群保持聯絡,更多相關資訊,請查閱我們的 社群 頁面。

Flutter 是開源的嗎?

是的,Flutter 是開源的。您可以在 GitHub 上獲取到它。

Flutter 以及其依存專案使用的是哪種軟體許可協議?

Flutter 包含兩個部分:一個使用動態連結二進位制檔案發行的引擎,以及引擎載入的 Dart 框架二進位制檔案。引擎使用了很多軟體元件,且包含許多依存內容。完整的說明和依存清單請檢視引擎的 許可協議

框架部分則自成一體,且 只有一份簡單的許可協議

另外,您使用的其他 Dart 程式碼包可能有其獨有的許可協議。

我如何確定我的 Flutter 應用該顯示哪些許可協議?

您可以使用 API 來確定需要顯示的許可協議。

目前有哪些人在開發 Flutter?

我們都在參與 Flutter 開發!我們都知道 Flutter 是一個開源專案。目前 Flutter 中的大部分都是由 Google 的工程師來開發。如果您喜歡 Flutter 的話,我們希望您加入開發者社群並 做出貢獻

Flutter 有哪些指導原則?

我們相信:

  • 為了觸達每一位潛在使用者,開發者需要針對多個行動平台釋出自己的應用。

  • 目前常用的 HTML 和 WebView 由於一些預設的互動響應(滾動、佈局等)以及向後相容等問題,很難獲得穩定的高幀率和精確的設計體驗。

  • 目前,開發同一個應用的不同平臺版本成本很高:這意味著不同的團隊、不同的程式碼庫、不同的工作流程以及不同的工具,等等。

  • 開發者需要一個簡單的、更好的方法來使用同一套程式碼庫開發應用的不同平臺版本。而且他們不希望在品質、細節和功能控制以及效能上有任何妥協。

我們目前集中於以下三件事:

功能控制
開發者應該能存取到系統所有層級的功能,且能獲得全面的控制權。這也意味著:

效能表現
使用者應該獲得流暢、響應迅捷且沒有卡頓的應用。這也意味著:

精確實現
每一個人都應該獲得精確、優美且富有表現力的移動應用體驗。

Apple 會拒絕我的 Flutter 應用嗎?

我們無法代 Apple 發言,但已經有很多使用類似 Flutter 的其他技術開發的應用。實際上,Flutter 與 Unity 使用了近乎一致的底層架構模型, Apple store 中最著名的遊戲也是使用它的引擎開發的。

Apple 最近評選的最佳設計應用也是使用 Flutter 開發的,其中包括 HamiltonReflectly

任何提交到 Apple store 的 Flutter 應用都應該遵守 Apple 的 規範