Flutter 快速上手,秒變大前端

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

滾動.gif

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體驗)

建立應用

  1. 選擇 File>New Flutter Project
  2. 選擇 Flutter application 作為 project 型別, 然後點選 Next
  3. 輸入專案名稱 (如 myapp), 然後點選 Next
  4. 點選 Finish
  5. 等待Android Studio安裝SDK並建立專案. 在專案目錄中,您應用程式的程式碼位於 lib/main.dart.

執行應用程式

定位到Android Studio 工具列:

image.png

  1. 在 target selector 中, 選擇一個執行該應用的Android裝置. 如果沒有列出可用,請選擇 Tools>Android>AVD Manager 並在那裡建立一個
  2. 在工具列中點選 Run圖示, 或者呼叫選單項 Run > Run.

▐ VS Code(輕量級編輯器,支援Flutter執行和偵錯)

建立應用

  1. 啟動 VS Code.
  2. 呼叫 View>Command Palette…
  3. 輸入 ‘flutter’, 然後選擇 ‘Flutter: New Project’ action
  4. 輸入 Project 名稱 (如myapp), 然後按確認鍵
  5. 指定放置專案的位置,然後按藍色的確定按鈕
  6. 等待專案建立繼續,並顯示main.dart檔案 在專案目錄中,您應用程式的程式碼位於 lib/main.dart.

執行應用程式

  1. 確保在VS Code的右下角選擇了目標裝置
  2. 按 F5 鍵或呼叫Debug>Start Debugging
  3. 等待應用程式啟動

▐ Terminal + 編輯器

建立應用

使用 flutter create 命令建立一個project:

$ flutter create myapp
$ cd myapp

執行應用程式

  • 檢查Android裝置是否在執行。如果沒有顯示, 請參照 設定
$ flutter devices

執行 flutter run 命令來執行應用程式:

$ flutter run

如果一切正常, 您應該在您的裝置或模擬器上會看到啟動的應用程式:

image.png

## 專案結構

┬
└ 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% 常用的元件即可。

image.png

RenderObjectWidget及其子類共有89個:

image.png

ProxyWidget及其子類共有34個:

image.png

StatelessWidget及其子類共有89個:

image.png

StatefulWidget的子類最多,高達141個

image.png

▐ 元件樹

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 元件。生成的元件樹如下:

image.png

讓 Text 元件居中,修改如下:

Scaffold(
  body: Center(
    child: Text('Hello world!'),
  ),
)

image.png

給應用程式新增 AppBar:

Scaffold(
  appBar: AppBar(),
  body: Center(
    child: Text('Hello world!'),
  ),
)

image.png

▐ 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 直播第一期預告


18D596D9-AB6C-48FC-80C2-9ED10319095A.png

關注「淘系技術」微信公眾號,一個有溫度有內容的技術社群~

image.png

原文連結:https://developer.aliyun.com/article/771969?

版權宣告:本文內容由阿里雲實名註冊使用者自發貢獻,版權歸原作者所有,阿里雲開發者社群不擁有其著作權,亦不承擔相應法律責任。具體規則請檢視《阿里雲開發者社群使用者服務協定》和《阿里雲開發者社群智慧財產權保護指引》。如果您發現本社群中有涉嫌抄襲的內容,填寫侵權投訴表單進行舉報,一經查實,本社群將立刻刪除涉嫌侵權內容。