簡介:近兩年Flutter的熱度不斷提升,無論在阿里還是外部公司,參與Flutter生態建設的人越來越多,Flutter作為跨端的UI框架,未來也有很大的可能像Rax一樣作為集團內營銷活動頁面搭建的DSL,所以目前學習Flutter,參與Flutter生態建設是一件時髦且有價值的事情,

Flutter是什么
Flutter是谷歌的移動UI框架,可以快速在iOS和Android上構建高質量的原生用戶界面,Flutter可以與現有的代碼一起作業,在全世界,Flutter正在被越來越多的開發者和組織使用,并且Flutter是完全免費、開源的,簡單來說,Flutter是一款移動應用程式SDK,包含框架、控制元件和一些工具,可以用一套代碼同時構建Android和iOS應用,并且性能可以達到原生應用一樣的性能,Flutter簡介
配置開發環境
Flutter開發可以在macOS,Linux或Windows上完成,雖然您可以在Flutter工具鏈中使用任何編輯器,但IntelliJ IDEA,Android Studio和Visual Studio Code的IDE插件可以簡化開發作業,
- 下載flutter SDK,地址
- 將flutter的bin目錄添加到path中,
- 執行flutter doctor命令,他會安裝flutter框架,包括dart,而且提示你任何其他需要安裝的依賴,
- 安裝其他依賴,
- 在IDE中安裝flutter插件,
體驗
? Android Studio (為Flutter提供完整的IDE體驗)
創建應用
- 選擇 File>New Flutter Project
- 選擇 Flutter application 作為 project 型別, 然后點擊 Next
- 輸入專案名稱 (如 myapp), 然后點擊 Next
- 點擊 Finish
- 等待Android Studio安裝SDK并創建專案. 在專案目錄中,您應用程式的代碼位于 lib/main.dart.
運行應用程式
定位到Android Studio 工具列:

- 在 target selector 中, 選擇一個運行該應用的Android設備. 如果沒有列出可用,請選擇 Tools>Android>AVD Manager 并在那里創建一個
- 在工具列中點擊 Run圖示, 或者呼叫選單項 Run > Run.
? VS Code(輕量級編輯器,支持Flutter運行和除錯)
創建應用
- 啟動 VS Code.
- 呼叫 View>Command Palette…
- 輸入 ‘flutter’, 然后選擇 ‘Flutter: New Project’ action
- 輸入 Project 名稱 (如myapp), 然后按回車鍵
- 指定放置專案的位置,然后按藍色的確定按鈕
- 等待專案創建繼續,并顯示main.dart檔案 在專案目錄中,您應用程式的代碼位于 lib/main.dart.
運行應用程式
- 確保在VS Code的右下角選擇了目標設備
- 按 F5 鍵或呼叫Debug>Start Debugging
- 等待應用程式啟動
? Terminal + 編輯器
創建應用
使用 flutter create 命令創建一個project:
$ flutter create myapp
$ cd myapp
運行應用程式
- 檢查Android設備是否在運行,如果沒有顯示, 請參照 設定,
$ flutter devices
運行 flutter run 命令來運行應用程式:
$ flutter run
如果一切正常, 您應該在您的設備或模擬器上會看到啟動的應用程式:

## 專案結構
┬
└ projectname
┬
├ android - Android部分的工程檔案
├ build - 專案的構建輸出目錄
├ ios - iOS部分的工程檔案
├ lib - 專案中的Dart源檔案
┬
└ src - 包含其他源檔案
└ main.dart - 自動生成的專案入口檔案,類似RN的index.js檔案
├ test - 測驗相關檔案
└ pubspec.yaml - 專案依賴組態檔類似于RN的 package.json
如何添加Flutter專案所需的依賴?
- 在Android中,你可以在Gradle檔案來添加依賴項;
- 在 iOS 中,通常把依賴添加到 Podfile 中;
- 在RN中,通常是由package.json來管理專案依賴;
Flutter 使用 Dart 構建系統和 Pub 包管理器來處理依賴,這些工具將Android 和 iOS native 包裝應用程式的構建委派給相應的構建系統,
dependencies:
flutter:
sdk: flutter
google_sign_in: ^3.0.3
在Flutter中,雖然在Flutter專案中的Android檔案夾下有Gradle檔案,但只有在添加平臺相關所需的依賴關系時才使用這些檔案,否則,應該使用pubspec.yaml來宣告用于Flutter的外部依賴項,
iOS也是一樣,如果你的 Flutter 工程中的 iOS 檔案夾中有 Podfile,請僅在添加iOS平臺相關的依賴時使用它,否則,應該使用pubspec.yaml來宣告用于Flutter的外部依賴項,
如何歸檔圖片資源以及如何處理不同解析度
雖然Android將resources 和 assets 區別對待,但在Flutter中它們都會被作為assets處理, 所有存在于Android上res/drawable- *檔案夾中的資源都放在Flutter的assets檔案夾中,
與Android類似,iOS 同樣將 images 和 assets 作為不同的東西,而 Flutter 中只有 assets,被放到 iOS 中 Images.xcasset 檔案夾下的資源在 Flutter 中被放到了 assets 檔案夾中,
在Flutter中assets可以是任意型別的檔案,而不僅僅是圖片,例如,你可以把 json 檔案放置到 my-assets 檔案夾中,
my-assets/data.json
記得在 pubspec.yaml 檔案中宣告 assets:
assets:
- my-assets/data.json
然后在代碼中我們可以通過 AssetBundle 來訪問它:
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
Future<String> loadAsset() async {
return await rootBundle.loadString('my-assets/data.json');
}
對于圖片,Flutter 像 iOS 一樣,遵循了一個簡單的基于像素密度的格式,Image assets 可能是 1.0x 2.0x 3.0x 或是其他的任何倍數,這個 devicePixelRatio 表示了物理像素到單個邏輯像素的比率,
Android不同像素密度的圖片和Flutter的像素比率的對應關系
ldpi 0.75x
mdpi 1.0x
hdpi 1.5x
xhdpi 2.0x
xxhdpi 3.0x
xxxhdpi 4.0x
舉個例子,要把一個名為 my_icon.png 的圖片放到 Flutter 工程中,你可能想要把它放到images檔案夾中,把圖片(1.0x)放置到 images 檔案夾中,并把其它解析度的圖片放在對應的子檔案夾中,并接上合適的比例系數,就像這樣:
images/my_icon.png // Base: 1.0x image
images/2.0x/my_icon.png // 2.0x image
images/3.0x/my_icon.png // 3.0x image
接下來就可以在pubspec.yaml檔案中這樣宣告這個圖片資源:
assets:
- images/my_icon.png
現在,我們就可以借助AssetImage來訪問它了,
return AssetImage("images/a_dot_burr.jpeg");
也可通過 Image widget 直接使用:
@override
Widget build(BuildContext context) {
return Image.asset("images/my_image.png");
}
如何歸檔strings資源,以及如何處理不同語言?
不像 iOS 擁有一個 Localizable.strings 檔案,Flutter目前沒有專門的字串資源系統,目前,最佳做法是將strings資源作為靜態欄位保存在類中,例如:
class Strings {
static String welcomeMessage = "Welcome To Flutter";
}
然后像如下方式來訪問它:
Text(Strings.welcomeMessage)
默認情況下,Flutter 只支持美式英語字串,如果你要支持其他語言,請引入 flutter_localizations 包,你可能也要引入 intl 包來支持其他的 i10n 機制,比如日期/時間格式化,
dependencies:
# ...
flutter_localizations:
sdk: flutter
intl: "^0.15.6"
要使用 flutter_localizations 包,還需要在 app widget 中指定 localizationsDelegates 和 supportedLocales,
import'package:flutter_localizations/flutter_localizations.dart';
MaterialApp(
localizationsDelegates: [
// Add app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'), // English
const Locale('he', 'IL'), // Hebrew
// ... other locales the app supports
],
// ...
)
這些代理包括了實際的本地化值,并且 supportedLocales 定義了 App 支持哪些地區,上面的例子使用了一個 MaterialApp ,所以它既有 GlobalWidgetsLocalizations 用于基礎 widgets,也有 MaterialWidgetsLocalizations 用于 Material wigets 的本地化,如果你使用 WidgetsApp ,則無需包括后者,注意,這兩個代理雖然包括了“默認”值,但如果你想讓你的 App 本地化,你仍需要提供一或多個代理作為你的 App 本地化副本,
當初始化時,WidgetsApp 或 MaterialApp 會使用你指定的代理為你創建一個 Localizations widget,Localizations widget 可以隨時從當前背景關系中訪問設備的地點,或者使用 Window.locale,
要訪問本地化檔案,使用 Localizations.of() 方法來訪問提供代理的特定本地化類,如需翻譯,使用 intl_translation 包來取出翻譯副本到 arb 檔案中,把它們引入 App 中,并用 intl 來使用它們,
更多 Flutter 中國際化和本地化的細節,請訪問 internationalization guide ,里面有不使用 intl 包的示例代碼,
組件
在 Flutter 中一切皆是 組件,僅僅 Widget 的子類和間接子類就有350多個,如此多的組件到底如果學習,真的需要學習 350 多個組件?經濟學中有一個著名的 二八定律 ,而我們學習 Flutter 也適用于二八定律,大部分組件是平時很少用到的,因此作為初學者,只需學習那 20% 常用的組件即可,

RenderObjectWidget及其子類共有89個:

ProxyWidget及其子類共有34個:

StatelessWidget及其子類共有89個:

StatefulWidget的子類最多,高達141個

? 組件樹
Flutter 創建App的時候,所有的組件最后會生成一個組件樹,例如如下代碼:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
),
home: Scaffold(
body: Text('Hello world!'),
),
);
}
}
main 函式是應用程式開始的地方,運行 MyApp 組件,生成的組件樹如下:

讓 Text 組件居中,修改如下:
Scaffold(
body: Center(
child: Text('Hello world!'),
),
)

給應用程式添加 AppBar:
Scaffold(
appBar: AppBar(),
body: Center(
child: Text('Hello world!'),
),
)

? StatefulWidget vs StatelessWidget
Flutter 中組件分為 無狀態組件(StatelessWidget) 和 有狀態組件(StatefulWidget)兩種,它們唯一的區別就是運行時 重新加載 組件的方式不同,StatelessWidget 組件重新加載時重新創建當前組件的實體,而StatefulWidget組件重新加載時不會重新創建實體,而是重新執行 build 函式,
StatelessWidget 組件創建的方式:
class StatelessWidgetDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}
build 函式回傳當前組件,此組件一旦創建將不可改變,build 函式只能執行一次,如果想重新繪制此組件,只能重新創建此組件新的實體,
StatefulWidget 組件創建的方式:
class StatefulWidgetDemo extends StatefulWidget {
@override
_StatefulWidgetDemoState createState() => _StatefulWidgetDemoState();
}
class _StatefulWidgetDemoState extends State<StatefulWidgetDemo> {
@override
Widget build(BuildContext context) {
return Container();
}
}
StatefulWidget 組件的創建方式和 StatelessWidget 不同,State<> 中的 build 函式回傳當前組件,有狀態的組件可以在其生命周期內多次重繪,即多次呼叫 build 函式,而不是創建一個新的實體,
StatefulWidget 組件重繪需要呼叫 setstate 方法,setstate 會使其自身及其子組件重繪,所以盡量封裝 StatefulWidget 組件,避免無效的重建和重繪,影響性能,
快速書寫小技巧:在 Android Studio 和 VS Code 中 輸入 stl 然后點擊回車,可以快速創建 StatelessWidget 組件,同理輸入 stf 點擊回車,可以快速創建 StatefulWidget 組件,這是編輯器 Live Templates 的功能,
? Material vs Cupertino
Flutter 中包含兩套風格的組件,分別是 Material 和 Cupertino ,Cupertino 是 iOS風格的組件,命名都帶 Cupertino 前綴,比如 CupertinoSlider 、 CupertinoDatePicker 等, Material Design 是由 Google 推出,旨在為手機、平板電腦、臺式機和“其他平臺”提供更一致、更廣泛的“外觀和感覺”,
Flutter 使用一套代碼在不同的平臺上表現一致,它不會根據不同的平臺繪制不同的外形,比如使用 AlertDialog 彈出警告框,不管在 Android 上,還是在 iOS上效果是一樣,
但有一些功能 Flutter 區分平臺,比如 ListView 滑動到底部時繼續滑動,Android 底部會出現淡藍色(默認情況下)拱形,而 iOS 上則沒有,這是因為 Flutter 在封裝此組件時在代碼中區分了平臺,所以在查看 Flutter 原始碼到程序中會經常看到根據不同的平臺做不同處理的情況,
總結
Flutter學習成本主要還是在組件的熟悉上,能數量常用組件就可以上手專案了,至于其他的控制元件只需大概瀏覽一下,做專案的時候遇到一些功能能夠想起 Flutter 已經提供了此組件就可以了,
參考
Flutter 中文網
Flutter 老孟
Flutter 直播第一期預告
關注「淘系技術」微信公眾號,一個有溫度有內容的技術社區~

原文鏈接:https://developer.aliyun.com/article/771969?
著作權宣告:本文內容由阿里云實名注冊用戶自發貢獻,著作權歸原作者所有,阿里云開發者社區不擁有其著作權,亦不承擔相應法律責任,具體規則請查看《阿里云開發者社區用戶服務協議》和《阿里云開發者社區知識產權保護指引》,如果您發現本社區中有涉嫌抄襲的內容,填寫侵權投訴表單進行舉報,一經查實,本社區將立刻洗掉涉嫌侵權內容,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/7922.html
標籤:其他
