Flutter實(shí)戰(zhàn) Flutter UI系統(tǒng)

2021-03-09 14:42 更新

在本書的前面章節(jié)中,我們多次提到"UI 系統(tǒng)"這個(gè)概念,本書中所指的 UI 系統(tǒng)特指:基于一個(gè)平臺(tái),在此平臺(tái)上實(shí)現(xiàn) GUI 的一個(gè)系統(tǒng),這里的平臺(tái)特指操作系統(tǒng),如 Android、iOS 或者 Windows、macOS。我們說過各個(gè)平臺(tái)UI系統(tǒng)的原理是相通的,也就是說無論是 Android 還是 iOS,他們將一個(gè)用戶界面展示到屏幕的流程是相似的,所以,在介紹 Flutter UI 系統(tǒng)之前,我們先看看 UI 系統(tǒng)的基本原理,這樣可以幫助讀者對(duì)操作系統(tǒng)和系統(tǒng)底層 UI 邏輯有一個(gè)清晰的認(rèn)識(shí)。

#硬件繪圖基本原理

提到原理,我們要從屏幕顯示圖像的基本原理談起。我們知道顯示器(屏幕)是由一個(gè)個(gè)物理顯示單元組成,每一個(gè)單元我們可以稱之為一個(gè)物理像素點(diǎn),而每一個(gè)像素點(diǎn)可以發(fā)出多種顏色,顯示器成相的原理就是在不同的物理像素點(diǎn)上顯示不同的顏色,最終構(gòu)成完整的圖像。

一個(gè)像素點(diǎn)能發(fā)出的所有顏色總數(shù)是顯示器的一個(gè)重要指標(biāo),比如我們所說的1600萬色的屏幕就是指一個(gè)像素點(diǎn)可以顯示出1600萬種顏色,而顯示器顏色是有 RGB 三基色組成,所以1600萬即2的24次方,即每個(gè)基本色(R、G、B)深度擴(kuò)展至8 bit(位),顏色深度越深,所能顯示的色彩更加豐富靚麗。

為了更新顯示畫面,顯示器是以固定的頻率刷新(從GPU取數(shù)據(jù)),比如有一部手機(jī)屏幕的刷新頻率是 60Hz。當(dāng)一幀圖像繪制完畢后準(zhǔn)備繪制下一幀時(shí),顯示器會(huì)發(fā)出一個(gè)垂直同步信號(hào)(如VSync), 60Hz的屏幕就會(huì)一秒內(nèi)發(fā)出 60次這樣的信號(hào)。而這個(gè)信號(hào)主要是用于同步 CPU、GPU 和顯示器的。一般地來說,計(jì)算機(jī)系統(tǒng)中,CPU、GPU和顯示器以一種特定的方式協(xié)作:CPU 將計(jì)算好的顯示內(nèi)容提交給 GPU,GPU 渲染后放入幀緩沖區(qū),然后視頻控制器按照同步信號(hào)從幀緩沖區(qū)取幀數(shù)據(jù)傳遞給顯示器顯示。

CPU 和 GPU 的任務(wù)是各有偏重的,CPU 主要用于基本數(shù)學(xué)和邏輯計(jì)算,而 GPU 主要執(zhí)行和圖形處理相關(guān)的復(fù)雜的數(shù)學(xué),如矩陣變化和幾何計(jì)算,GPU 的主要作用就是確定最終輸送給顯示器的各個(gè)像素點(diǎn)的色值。

#操作系統(tǒng)繪制API的封裝

由于最終的圖形計(jì)算和繪制都是由相應(yīng)的硬件來完成,而直接操作硬件的指令通常都會(huì)有操作系統(tǒng)屏蔽,應(yīng)用開發(fā)者通常不會(huì)直接面對(duì)硬件,操作系統(tǒng)屏蔽了這些底層硬件操作后會(huì)提供一些封裝后的 API 供 操作系統(tǒng)之上的應(yīng)用調(diào)用,但是對(duì)于應(yīng)用開發(fā)者來說,直接調(diào)用這些操作系統(tǒng)提供的 API 是比較復(fù)雜和低效的,因?yàn)椴僮飨到y(tǒng)提供的 API 往往比較基礎(chǔ),直接調(diào)用需要了解 API 的很多細(xì)節(jié)。正是因?yàn)檫@個(gè)原因,幾乎所有用于開發(fā) GUI 程序的編程語言都會(huì)在操作系統(tǒng)之上再封裝一層,將操作系統(tǒng)原生 API 封裝在一個(gè)編程框架和模型中,然后定義一種簡(jiǎn)單的開發(fā)規(guī)則來開發(fā) GUI 應(yīng)用程序,而這一層抽象,正是我們所說的“UI”系統(tǒng),如 Android SDK 正是封裝了 Android 操作系統(tǒng) API,提供了一個(gè)“UI描述文件 XML+Java 操作 DOM”的 UI 系統(tǒng),而 iOS 的 UIKit 對(duì) View 的抽象也是一樣的,他們都將操作系統(tǒng) API 抽象成一個(gè)基礎(chǔ)對(duì)象(如用于2D圖形繪制的Canvas),然后再定義一套規(guī)則來描述 UI,如 UI 樹結(jié)構(gòu),UI 操作的單線程原則等。

#Flutter UI系統(tǒng)

我們可以看到,無論是 Android SDK 還是 iOS 的 UIKit 的職責(zé)都是相同的,它們只是語言載體和底層的系統(tǒng)不同而已。那么可不可以實(shí)現(xiàn)這么一個(gè)UI系統(tǒng):可以使用同一種編程語言開發(fā),然后針對(duì)不同操作系統(tǒng) API 抽象一個(gè)對(duì)上接口一致,對(duì)下適配不同操作系統(tǒng)的的中間層,然后在打包編譯時(shí)再使用相應(yīng)的中間層代碼?如果可以做到,那么我們就可以使用同一套代碼編寫跨平臺(tái)的應(yīng)用了。而 Flutter 的原理正是如此,它提供了一套 Dart API,然后在底層通過 OpenGL 這種跨平臺(tái)的繪制庫(內(nèi)部會(huì)調(diào)用操作系統(tǒng) API)實(shí)現(xiàn)了一套代碼跨多端。由于 Dart API 也是調(diào)用操作系統(tǒng) API,所以它的性能接近原生。

注意,雖然 Dart 是先調(diào)用了 OpenGL,OpenGL 才會(huì)調(diào)用操作系統(tǒng) API,但是這仍然是原生渲染,因?yàn)?OpenGL 只是操作系統(tǒng) API 的一個(gè)封裝庫,它并不像 WebView 渲染那樣需要 JavaScript 運(yùn)行環(huán)境和 CSS 渲染器,所以不會(huì)有性能損失。

至此,我們已經(jīng)介紹了 Flutter UI 系統(tǒng)和操作系統(tǒng)交互的這一部分原理,現(xiàn)在需要說一些它對(duì)應(yīng)用開發(fā)者定義的開發(fā)標(biāo)準(zhǔn)。其實(shí)在前面的章節(jié)中,我們已經(jīng)對(duì)這個(gè)標(biāo)準(zhǔn)非常熟悉了, 簡(jiǎn)單概括就是:組合和響應(yīng)式。我們要開發(fā)一個(gè) UI 界面,需要通過組合其它 Widget 來實(shí)現(xiàn),F(xiàn)lutter 中,一切都是 Widget,當(dāng) UI 要發(fā)生變化時(shí),我們不去直接修改 DOM,而是通過更新狀態(tài),讓 Flutter UI 系統(tǒng)來根據(jù)新的狀態(tài)來重新構(gòu)建 UI。

講到這里,讀者可能發(fā)現(xiàn) Flutter UI 系統(tǒng)和 Flutter Framework 的概念是差不多的,的確如此,之所以用“UI系統(tǒng)”,是因?yàn)槠渌脚_(tái)中可能不這么叫,我們只是為了概念統(tǒng)一,便于描述,讀者不必糾結(jié)于概念本身。

在接下來的小節(jié)中,我們先詳細(xì)介紹一下Element、RenderObject,它們是組成 Flutter UI 系統(tǒng)的基石。最后我們?cè)俜治鲆幌?Flutter 應(yīng)用啟動(dòng)和運(yùn)行的整體過程。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)