Flutter(一)Hello, Flutter!

語言: CN / TW / HK

1. 移動端開發演變過程

1.1 原生開發

原生應用程式是指某一個移動平臺(比如iOS或安卓)所特有的應用,使用相應平臺支援的開發工具和語言,直接呼叫系統SDK API。

  • Android原生應用:使用Java或Kotlin直接呼叫Android SDK開發的應用程式;

  • iOS原生應用:通過Objective-C或Swift語言直接呼叫iOS SDK開發的應用程式。

主要優勢:

  • 可直接無障礙的訪問平臺全部功能;

  • 速度快、效能高、可以實現複雜動畫及繪製,整體使用者體驗好;

主要缺點:

  • 開發成本高;不同平臺必須維護不同程式碼,人力成本、測試成本大;

  • 內容固定,動態化弱,大多數情況下,有新功能更新時只能發版,但應用上架、稽核是需要週期的,這對高速變化的網際網路時代來說是很難接受的;

針對動態化和開發成本兩個問題,誕生了一些跨平臺的動態化框架。👇👇👇👇👇👇

1.2 跨平臺技術簡介

這裡的跨平臺指Android和iOS兩個平臺。根據其原理,主要分為三類:

  • H5+原生(Cordova、Ionic、微信小程式)=> Hybrid/混合開發

  • 原理:APP需要動態變化的內容通過H5來實現,進一步通過原生的網頁載入控制元件WebView (Android)或WKWebView(iOS)來載入。

  • WebView實質上是一個瀏覽器核心,其JavaScript依然執行在一個許可權受限的沙箱中,所以對於大多數系統能力都沒有訪問許可權,如無法訪問檔案系統、不能使用藍芽等。所以,對於H5不能實現的功能,都需要原生去做。

  • 核心:混合框架會在原生程式碼中預先實現一些訪問系統能力的API, 暴露給WebView以供JavaScript呼叫,讓WebView成為JavaScript與原生API之間通訊的橋樑,主要負責JavaScript與原生之間傳遞呼叫訊息 => JsBridge(WebView JavaScript Bridge)

  • JavaScript開發+原生渲染 (React Native、Weex、快應用)

這裡主要介紹下 React Native 特點

  • 和 React 原理相似,支援響應式程式設計,開發者只需關注狀態轉移,不需要關注UI繪製;

  • React 和 React Native 主要的區別在於虛擬DOM對映的物件是什麼:

  • React中虛擬DOM最終會對映為瀏覽器DOM樹;

  • RN中虛擬DOM會通過 JavaScriptCore 對映為原生控制元件樹。(兩步)

  • 第一步:佈局訊息傳遞; 將虛擬DOM佈局資訊傳遞給原生;

  • 第二步:原生根據佈局資訊通過對應的原生控制元件渲染控制元件樹;

  • 優點:

  • 採用Web開發技術棧,社群龐大、上手快、開發成本相對較低。

  • 原生渲染,效能相比H5提高很多。

  • 動態化較好,支援熱更新。

  • 不足:

  • 渲染時需要JavaScript和原生之間通訊,在有些場景如拖動可能會因為通訊頻繁導致卡頓;

  • JavaScript為指令碼語言,執行時需要JIT(Just In Time),執行效率和AOT(Ahead Of Time)程式碼仍有差距;

  • 由於渲染依賴原生控制元件,不同平臺的控制元件需要單獨維護。

RN架構升級,進行中,解決頻繁和原生通訊的瓶頸問題。)

  • 自繪UI+原生(QT for mobile、Flutter)

  • QT for mobile(是移動端開發跨平臺自繪引擎的先驅,也是烈士。)

  • Flutter 👇👇👇👇👇👇

2. Flutter 介紹

Flutter 是 Google 推出並開源的移動應用框架,主打跨平臺、高保真、高效能。

2.1 跨平臺自繪引擎

Flutter 與用於構建應用程式的其他框架不同,是因為 Flutter 既不使用 WebView 也不使用作業系統的原生控制元件。相反,Flutter 自己實現了自繪引擎。這樣不僅能保證一套程式碼可以同時執行在 IOS 和 Android 平臺上,還保證了 Android 和 IOS 上 UI 的一致性,而且也可以避免對原生控制元件依賴帶來的限制和高昂的成本維護,也不用和native層做過多的通訊,大大提高效能。

Flutter 使用 Skia 作為其2D渲染引擎,Skia 是一個 Google 的2D圖形處理函式,包含字元、座標轉換,以及點陣圖都有高效能且簡介的表現,Skia 是跨平臺的,並提供了非常友好的 API ,目前 Google Chrome 瀏覽器和 Android 均採用 Skia 作為其繪圖引擎。

目前 Flutter 預設支援 Android、IOS、Fuchsia(Google新的自研作業系統)、鴻蒙四個移動平臺,也支援 Web 開發(Flutter for web)、 PC 、小程式的開發。

2.2 採用Dart語言

這是一個很有意思也很有爭議的問題,Flutter為什麼選擇Dart語言?

開發效率高。Dart執行時和編譯器支援Flutter兩個關鍵特性的組合:

基於JIT的快讀開發週期:Flutter在開發階段採用JIT模式。這樣就避免了每次改動都要進行編譯,極大節省了開發時間;並且在iOS和Android模擬器或真機上可以實現毫秒級熱過載,並且不會丟失狀態。

基於AOT的釋出包:Flutter 在釋出時間可以通過AOT生成高效的ARM程式碼以保證應用效能。而JavaScript則不具有這個能力(雖然可以通過打包工具實現)。

目前,程式主要有兩種執行方式:靜態編譯與動態解釋。
靜態編譯:在執行前全部被翻譯為機器碼
👉 AOT(Ahead of time)即“提前編譯”; AOT程式的典型代表是用C/C++開發的應用,他們必須在執行前編譯成機器碼; 動態解釋(解釋執行)則是一句一句邊翻譯邊執行
👉 JIT(Just-in-time)即“即時編譯”。 JIT的代表則非常多,如JavaScript、Python等。
事實上,所有指令碼語言都支援JIT模式。但需要注意的是,JIT和AOT 指的是程式執行方式,和編譯語言並非強相關,有些語言既可以以JIT方式執行也可以以AOT方式執行,如Java、Python,他們可以在第一次執行時編譯成中間位元組碼,然後在之後執行時可以直接執行位元組碼,也許有人會說,中間位元組碼並非機器碼,在程式執行時仍需動態將位元組碼轉換成機器碼,是的,這沒有錯,不過通常我們區分是否為AOT的標準就是看程式碼在執行前是否需要編譯,只要需要編譯,無論其編譯產物是位元組碼還是機器碼,都屬於AOT(不必糾結於概念,概念是為了傳達精神而發明的,理解原理即可)。

高效能。Flutter提供流暢、高保真的UI體驗,為了實現這一點,Flutter中需要能夠在每個動畫幀中執行大量的程式碼。這意味著需要一種既能提供高效能的語言,而不會出現丟幀的週期性暫停的問題,而Dart支援AOT,在這一點上可以比JavaScript做的更好。

型別安全。由於Dart 是型別安全的語言,支援靜態型別檢查,所以可以在編譯前發現一些型別錯誤,並排除潛在問題。這一點對於前端開發者極具吸引力,為了解決JavaScript弱型別的缺點,前端社群出現了很多給JavaScript程式碼新增靜態型別檢測的擴充套件語言和工具,如:微軟的TypeScript、Facebook的Flow。而 Dart 本身就支援靜態型別,這是他的一個重要優勢。

快速記憶體分配。Flutter框架使用函式式流,這使得它在很大程度上依賴底層記憶體分配器。因此,擁有一個能夠有效的處理瑣碎任務的記憶體分配器將顯得十分重要。但其實在記憶體分配上Dart並沒有超越JavaScript,只是Flutter需要,Dart 恰好滿足。

Dart 團隊就在 Flutter身邊。Dart 語言也是谷歌推出的,由於有Dart團隊的積極投入,Flutter團隊可以獲得更多、更方便的支援。

例如:Dart 最初並沒有提供原生二進位制檔案的工具鏈(這對於實現可預測的高效能有很大幫助),但是現在它實現了,因為 Dart 團隊專門為 Flutter 構建了它。 Dart VM 之前已經針對吞吐量進行了優化,但團隊現在正忙於優化VM的延遲,這對於Flutter的工作負載更為重要。

2.3 高效能

Flutter 高效能主要是靠以上剛剛介紹的兩點來保證的:

採用 Dart 語言開發。Dart 在 JIT(即時編譯)模式下,速度與 JavaScript 基本持平,但是 Dart 支援 AOT,當以 AOT 模式執行時,JavaScript 就遠遠追不上了。速度的提升對高幀率下的資料計算很有幫助。

使用自己的渲染引擎來繪製 UI,佈局資料由 Dart 語言直接控制,在佈局過程中不需要像 RN 那樣要在 JavaScript 和 Native 之間通訊,這在一些滑動拖動場景下有明顯優勢,因為在滑動和拖動過程中往往都會引起佈局發生變化,所以 JavaScript 需要在 Native 之間不停的同步佈局資訊,這和在瀏覽器中要 JavaScript 頻繁操作 DOM 所帶來的問題是相同的,都會帶來比較大的效能開銷。

2.4 響應式框架

借鑑 React 響應式的 UI 框架設計思想。中心思想是用 widget 構建你的 UI。 Widget 描述了他們的檢視在給定其當前配置和狀態時應該看起來像什麼。當 widget 的狀態發生變化時,widget 會重新構建 UI,Flutter 會對比前後變化的不同, 來確定底層渲染樹從一個狀態轉換到下一個狀態所需的最小更改(類似於 React/Vue 中虛擬 DOM 的 diff 演算法)。

2.5 多端編譯

2.5.1 移動端

  • 打包 Android 併發布手機商店 👉 VSCode

  • 打包命令

    flutter build apk

  • 釋出:

  • 註冊各大應用市場開發者賬號

  • 建立要釋出的app資訊

  • 按照流程上傳

  • 打包 IOS 併發布 Apple Store 👉 XCode

  • 打包命令

    flutter build ios

  • 釋出:

  • 註冊 Apple 開發者

  • 建立要釋出的app資訊

  • 配置鑰匙串

  • 在xcode配置apple stoer的證書和bundle id

  • xcode>Product>Archive>Distribute App

2.5.2 Web端

  • Flutter 2.x

  • 檢查是否支援web開發 $ flutter devices

  • 打包命令

    flutter build web --web-renderer html # 開啟速度最快,相容性好 flutter build web # 開啟速度一般,相容性好 flutter build web --web-renderer canvaskit # 開啟速度最慢,相容性好

  • 部署:直接部署到伺服器上即可

3. Flutter 框架結構

3.1 移動架構

3.1.1 Framework 框架層

框架層。這是一個純dart實現的響應式框架,它實現了一套基礎庫。

  • 底下兩層(Foundation、Animation、Painting、Gestures)在Google的一些影片中被合併為一個Dart UI層,對應的是Flutter中的dart:ui包,它是Flutter引擎暴露的底層UI庫,提供動畫、手勢及繪製能力。

  • Rendering 層,是一個抽象層,它依賴於 Dart UI ,這一層會構建一個UI樹,當UI有變化時,會計算出有變化的部分,然後更新UI樹,最終將UI樹繪製到螢幕上,這個過程類似於React中的虛擬dom。Rendering層可以說是Flutter UI 框架的核心,它除了確定每個UI元素的位置、大小之外,還要呼叫底層dart:ui進行座標變化和繪製。

  • Widgets層是Flutter提供的一套基礎元件

  • Material 和 Cupertino 是 Flutter 提供的兩種視覺風格的元件庫,Material 安卓風格,Cupertino 是IOS風格。

實際開發過程中,主要都是和最上面的Widgets、Material/Cupertino兩層打交道。

3.1.2 Engine 引擎層

純C++實現的SDK,為Flutter的核心,提供了Flutter核心API的底層實現。其中包括了Dart執行時、Skia引擎、文字排版引擎等,是連線框架和系統(Android/IOS)的橋樑。在程式碼呼叫dart:ui庫時,呼叫最終會走到Engine層,然後實現真正的繪製邏輯。

3.1.3 Embedder 嵌入層

嵌入層基本是由平臺對應的語言來實現的。例如:在Android上,是由Java和C++ 來實現的,IOS是由Object-C和Object-C++來實現的。

嵌入層為Flutter提供了一個入口,Flutter系統是通過該入口訪問底層系統提供的服務,例如輸入法、繪製surface等。

3.2 Web端架構

3.3 移動端開發方式架構比較

4. 移動端開發對比

4.1 方案對比

4.2 效能對比

感興趣 這裡 有詳細的效能對比介紹,不贅述。

5. Flutter 周邊——除錯工具

Flutter日誌 和 print(); 是比較常用的檢查資料的除錯方法,但是不支援圖形化介面、佈局等的檢查。👇👇👇👇👇👇

5.1 inspector 外掛

視覺化和瀏覽Flutter Widget樹的工具。檢視渲染樹,瞭解佈局資訊。

5.2 Dev Tools

5.3 UME

位元組 Flutter Infra 團隊推出的開源 應用內 除錯工具。

Pub.dev 釋出地址
https://pub.flutter-io.cn/packages/flutter_ume
GitHub 開源地址
https://github.com/bytedance/flutter_ume

功能 => UI 檢查、程式碼檢視、日誌檢視、效能工具 ...

服務於 => 設計師、產品經理、研發工程師或質量工程師 ...

  • UI 檢查外掛包。點選 widget 獲取 widget 基本資訊、程式碼所在目錄、widget 層級結構、RenderObject 的 build 鏈與描述的能力,顏色拾取與對齊標尺在視覺驗收環節提供有力幫助。

  • 程式碼檢視外掛。允許使用者輸入關鍵字,進行模糊匹配,對任意程式碼內容的檢視能力。

  • 日誌檢視。日誌資訊可通過統一面板提供篩選、匯出等。

  • 效能檢測包。提供了當前 VM 物件例項數量與記憶體佔用大小等資訊。

6. Flutter 周邊——學習路線

6.1 學習社群

  • Flutter 中文網 👉 入門文件

  • Flutter 中文社群 👉 入門文件

  • 鹹魚Flutter 👉 可借鑑的架構方案

  • 掘進Flutter 👉 專業性強的部落格

  • StackOverflow 👉 問答社群,我遇到的flutter的問題,這裡的答案最靠譜

  • 原始碼及註釋 👉 🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️🙋‍♂️ 最方便開發時查詢

6.2 學習路線

1、準備期

  • 目標:

  • 通過學習 Dart 基本語法,瞭解 Flutter 中的 Dart 的基本使用;

  • 學習 Flutter 提供的基礎佈局和基本內容元件,完成基本頁面展示。

  • 技術點:

  • Dart語法

  • Flutter 基礎元件

  • Material Design

  • Cupertino

    > *   [Flutter Widget概述](https://flutterchina.club/widgets-intro/)
    
    > *   [Flutter Layout Widget](https://flutter.dev/docs/development/ui/widgets/layout)
    
    > *   [Flutter 佈局教程](https://flutterchina.club/tutorials/layout/)
    
    > *   [Material Design](https://material.io/)
    
  • Flutter 事件處理

  • Flutter 頁面跳轉

2、入門期

3、進階期

6.3 學習開源專案

UI元件集專案 FlutterUnit

7. Flutter 周邊——JS2Flutter

JS 轉 Dart => JS2Flutter