目錄

常見問題與解答

目錄

簡介

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

什麼是 Flutter?

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

哪些人會用到 Flutter?

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

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

對於設計師來說,Flutter 提供了一個能夠實現高保真度使用者體驗的畫布。 Fast 公司評價 Flutter 是 一個設計靈感的源泉,提供了將概念轉換為生產程式碼的能力,卻沒有典型的框架強加的妥協。 Flutter 同時也是一個能提高生產力的原型工具,例如可拖入檔案載入的 FlutterFlow 和基於 Web 的 IDE Zapp!

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

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

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

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

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

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

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

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

誰創造了 Flutter?

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

誰在使用 Flutter?

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

Flutter 有哪些獨到之處?

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

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

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

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

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

Flutter 能夠為我們提供什麼?

Flutter SDK 裡有什麼?

Flutter 包括了:

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

  • 現代回應式風格框架

  • Material Design 風格及 iOS 風格豐富的 widget 元件

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

  • 原生平台互動性和外掛 API 可以連線系統及第三方 SDK

  • Headless 測試執行器,用於在 Windows、Linux 和 Mac 上執行測試

  • 用於測試、除錯和分析你的應用程式的 Flutter DevTools

  • 指令行工具,用於建立、開發、測試和編譯你的應用程式

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

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

你也可以在指令行中使用 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。你可以透過 widget 目錄 瞭解支援 Material 2 和 3 的 widget。

Flutter 帶有測試框架嗎?

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

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

Flutter 是否附帶除錯工具?

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

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

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

技術篇

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

Flutter 使用 C、C++、Dart、Skia (2D 渲染引擎) 以及 Impeller (iOS 預設的渲染引擎) 建立。你可以參閱下面這張 架構圖 來理解其主要建立。若你需要瞭解 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 和應用程式碼。這個工作機制與很多遊戲引擎頗為相似。

在 debug 模式下,Flutter 使用虛擬環境 (VM) 來執行程式碼,使其可以保持狀態並且可以熱過載,這個功能讓你可以在無需重新編譯的前提下立刻看到新程式碼生效的結果。在 debug 模式下,你會看到右上角有一個 “debug” 的橫幅條,它會提醒你 debug 模式下的效能並不代表 release 模式的效能。

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 程式碼嗎?

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 實測得出。

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

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

How does Flutter define a pixel?

Flutter uses logical pixels, and often refers to them merely as “pixels”. Flutter’s devicePixelRatio expresses the ratio between physical pixels and logical CSS pixels.

賦能

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 嗎?

是的,你可以在我們網上內的 混合應用 章節中學習。

我能訪問傳感器、本地儲存之類的平台服務和 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 上的問題追蹤 來獲得相關訊息。

Flutter 是否提供 ABI 支援?

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 的 IDE 外掛,你就可以在 profile 或者 release 模式下啟動應用,對於 VS Code 而言,你可以使用 Run > Start debugging 或者 Run > Run without debugging 選單選項。對於 IntelliJ 而言,你可以使用 Run > Flutter run in Profile Mode 或者 Release Mode 選單選項。

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

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

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

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

事件驅動程式設計 (event-driven programming)
使用者的互動操作被包裝成事件物件,這些物件傳送給被各個 event handler 註冊的回呼方法。螢幕內容的更新使用的也是類似的回呼機制。比如,做為動畫系統建立基礎的 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 方法通常都是一個單一表示式,它包含多級巢狀的建構式函式,且使用 Dart 嚴格的宣告式子集編寫。這些巢狀的表示式可以與合適的標記語言互相轉換。比如,UserAccountsDrawerHeader 這個 widget 就有一個很長的 build 方法 (20 多行),由一個巢狀的表示式構成。這種正規化也可以和指令式混合使用,以實現某些很難用純宣告式的方法實現的 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 cfug-dev@googlegroups.com or seek us out on Discord.

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

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

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

我們也希望你加入我們的郵件討論 cfug-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 的 規範