什么是 Flutter?
Flutter mobile app SDK是一種新的方式來構(gòu)建漂亮的原生移動應(yīng)用程序,擺脫過去常見的“千篇一律”的應(yīng)用程序。用過Flutter的人都對它贊賞有加;
相比較其他新型系統(tǒng),人們想知道是什么讓它與眾不同,換句話說,“Flutter的創(chuàng)新和令人興奮的內(nèi)容到底是什么?”,這是個好問題。本文將從技術(shù)角度回答這個問題。
首先,先來講點歷史。
移動應(yīng)用程序開發(fā)的簡史
移動應(yīng)用程序開發(fā)是一個相對較新的領(lǐng)域。 第三方開發(fā)人員已經(jīng)能夠在不到十年的時間里構(gòu)建移動應(yīng)用程序,所以此類工具仍在不斷發(fā)展的現(xiàn)象并不令人覺得奇怪。
平臺軟件開發(fā)工具(Platform SDK)
Apple iOS SDK于2008年發(fā)布,Google Android SDK于2009年發(fā)布。這兩個SDK分別基于不同的語言:Objective-C和Java。
在這個模型中,你的app通過與平臺(Platform)通信以創(chuàng)建小部件(Widgets)或訪問相機等服務(wù)。 窗口小部件會呈現(xiàn)在屏幕畫布上(Canvas),同時事件(Event)會被傳遞到窗口小部件。 雖然這是一個簡單的架構(gòu),但你幾乎要為每個平臺創(chuàng)建單獨的應(yīng)用程序,因為在不同平臺上的小部件也是不同的。這樣的軟件開發(fā)難度可想而知更不用說還要使用原生語言開發(fā)了。
網(wǎng)頁視圖(Web view)
Web View是史上第一個跨平臺框架,它基于JavaScript和WebViews,其例子包括一系列相關(guān)框架 :PhoneGap,Apache Cordova,Ionic等。 在Apple發(fā)布iOS SDK之前,Apple建議第三方開發(fā)人員使用Webapp為iPhone編寫程序。因此使用Web技術(shù)構(gòu)建跨平臺應(yīng)用程序是具有代表性的一步。
在這個框架中,你的app會創(chuàng)建HTML并將其顯示在平臺上的WebView中。 請注意,像JavaScript這樣的語言很難直接與本機代碼(如服務(wù))對話,因此它們會經(jīng)歷一個“橋”,在JavaScript領(lǐng)域和本機領(lǐng)域之間進(jìn)行上下文切換。 由于平臺服務(wù)通常不會經(jīng)常被調(diào)用,因此這不會導(dǎo)致太多性能問題。
響應(yīng)視圖(Reactive Views)
當(dāng)下,滿大街都是像ReactJS(或是其他)這樣的響應(yīng)式網(wǎng)頁編程框架,主要是因為它們借鑒了響應(yīng)式編程的編程模式來簡化Web視圖。2015年,React Native的建立給手機app上的響應(yīng)式開發(fā)提供了許多便利。
React Native非常受歡迎,但是如果它想從JavaScript域中訪問處于平臺域(Platform)中的平臺部件(Widget),它就必須通過橋接器(Bridge)。 通常,小部件需要被頻繁調(diào)用(在動畫,轉(zhuǎn)換期間或當(dāng)用戶用手指“刷”屏幕上的某些內(nèi)容時,調(diào)用次數(shù)被限制在了每秒最多60次),這就可能會導(dǎo)致性能問題。就像one article about React Native所說:
這是理解React Native性能的主要關(guān)鍵之一。 每個領(lǐng)域本身都非??臁?當(dāng)我們從一個領(lǐng)域轉(zhuǎn)移到另一個領(lǐng)域時,通常會出現(xiàn)性能瓶頸。 為了構(gòu)建高性能的React Native應(yīng)用程序,我們必須將橋上的數(shù)據(jù)傳遞保持在一定限度之內(nèi)。
Flutter
與React Native一樣,F(xiàn)lutter也提供了響應(yīng)式視圖。 Flutter采用不同的方法來避免因使用編譯的編程語言(即Dart)而需要JavaScript橋接從而導(dǎo)致的性能問題。Dart是“提前”(AOT)編譯為多個平臺的原生代碼。 它能夠與Flutter與平臺進(jìn)直接行通信,而無需通過執(zhí)行上下文切換的JavaScript橋接器。 此外,編譯為原生代碼的應(yīng)用程序還可以縮短程序的啟動時間。
事實上,F(xiàn)lutter是唯一的,不需要Javascript橋接的手機SDK。這足以使得它變得很有趣并值得一試。不僅如此,F(xiàn)lutter還有一些更具革命性的東西,比如它實現(xiàn)小部件的方式。
Flutter的小部件 (Widget)
窗口小部件是影響和控制應(yīng)用程序視圖和界面的元素。 說小部件是移動應(yīng)用程序最重要的部分之一并不夸張。 事實上,單獨的一個小部件就足以創(chuàng)建或破壞一個應(yīng)用程序。
- 小部件的外觀和感覺是至關(guān)重要的。 小部看起來好看,需要適配各種屏幕尺寸。同時,他們也需要感覺自然。
- 小部件必須快速執(zhí)行: 創(chuàng)建窗口小部件樹,伸縮窗口小部件(實例化他們的子窗口),將它們放在屏幕上,渲染它們,或(尤其是)為它們設(shè)置動畫。
- 對于現(xiàn)代應(yīng)用程序,窗口小部件應(yīng)該是可擴展和可自定義的。開發(fā)人員希望能夠添加令人愉快的新窗口小部件,并自定義與應(yīng)用程序的品牌相適應(yīng)的窗口小部件。
Flutter有一個新的架構(gòu),包括良好的外觀,反應(yīng)速度快,可定制和可擴展的小部件。 沒錯,F(xiàn)lutter不使用平臺小部件(或DOM WebViews),它提供了自己的小部件。
Flutter將小部件和渲染器放到應(yīng)用程序域中而不是傳統(tǒng)的平臺域中,這使小部件可以自定義和擴展。 Flutter要求平臺提供畫布(Canvas)(應(yīng)用程序在其中呈現(xiàn)小部件以便它們可以出現(xiàn)在設(shè)備屏幕上)及訪問事件(觸摸,計時器等)和服務(wù)(位置,相機等)。
Dart程序(綠色)和本機平臺代碼(藍(lán)色,iOS或Android)之間仍然有一個接口,可以進(jìn)行數(shù)據(jù)編碼和解碼,但這比JavaScript橋接器快幾個數(shù)量級。
事實上,將小部件和渲染器移動到應(yīng)用程序中會影響應(yīng)用程序的大小。 Android上Flutter應(yīng)用程序的最小大小約為4.7MB,相當(dāng)于使用其他工具構(gòu)建的最小應(yīng)用程序的大小。
本文的其余部分將討論這些好處。
布局(Layout)
在Flutter中最大的提升之一是Layout(布局)。Layout(布局)基于一些規(guī)則(也叫約束)決定了widgets(小部件)的大小和位置。
傳統(tǒng)上,布局使用大量能夠被應(yīng)用到(幾乎)所有小部件的規(guī)則。這些規(guī)則被接入多種布局思路。我們以CSS布局為例,因為它很知名(盡管 安卓和iOS的布局基本上是相似的)。CSS具有的一些屬性(規(guī)則)可應(yīng)用于HTML元素(小部件)。CSS3定義了375個屬性。
CSS包含許多布局模型,包括(多個)框模型、浮動元素、表、多列文本、分頁媒體等等。后來又添加了其他的布局模型,比如flexbox和grid,因為開發(fā)人員和設(shè)計師需要對布局進(jìn)行更多的控制,并使用表格和透明圖像來獲得他們想要的東西。在傳統(tǒng)布局中,開發(fā)人員無法添加新的布局模型,因此必須將flexbox和grid添加到CSS中,并在所有瀏覽器上實現(xiàn)。
傳統(tǒng)布局的另一個問題是,規(guī)則可以相互交互(甚至沖突),元素通常有許多規(guī)則應(yīng)用于它們。這使得布局變慢。更糟糕的是,布局性能通常是N-的平方階,因此隨著元素數(shù)量的增加,布局會變得更慢。
Flutter最初是由谷歌的Chrome瀏覽器團隊成員進(jìn)行的一項實驗。我們想看看如果我們忽略傳統(tǒng)的布局模型,是否可以構(gòu)建更快的渲染器。幾周后,我們?nèi)〉昧孙@著的性能提升。我們發(fā)現(xiàn):
- 大多數(shù)布局相對簡單,例如:滾動頁面上的文本、大小和位置僅取決于顯示大小的固定矩形,以及一些表格、浮動元素等。
- 大多數(shù)布局是小部件子樹的本地布局,該子樹通常使用一個布局模型,因此這些小部件只需要支持少量規(guī)則。
我們意識到,如果我們把它反過來看,布局可以大大簡化:
- 每個小部件將指定自己的簡單布局模型,而不是一大堆可以應(yīng)用于任何小部件的布局規(guī)則。?因為每個小部件需要考慮的布局規(guī)則要少得多,所以可以對布局進(jìn)行大量優(yōu)化。
- 為了進(jìn)一步簡化布局,我們幾乎把所有東西都變成了一個小部件。
下面是Flutter代碼,用于創(chuàng)建一個布局簡單的小部件樹:
new Center(child: new Column(children: [new Text('Hello, World!')),new Icon(Icons.star, color: Colors.green)]))
這段代碼足夠語義化,您可以很容易地想象它將產(chǎn)生什么,但是結(jié)果顯示如下:
在這段代碼中,一切都是一個小部件,包括布局在內(nèi)。中心(Center)小部件將它的子部件放在其父部件(例如屏幕)中。列布(Column)局小部件垂直地排列其子部件(小部件列表)。該列包含一個文本(Text)小部件和一個圖標(biāo)(Icon)小部件(圖標(biāo)小部件具有屬性及其顏色)。
在Flutter中,置于中心和填充的是小部件。主題是小部件,適用于它們的子組件。甚至應(yīng)用程序和導(dǎo)航都是小部件。
Flutter 包含許多用于布局的小部件,不僅包括列,還包括行、網(wǎng)格、列表等。此外,F(xiàn)lutter還有一個獨特的布局模型,我們稱之為“sliver layout model”,用于滾動。Flutter中的布局非???,可以用來滾動頁面。想一下。滾動必須是即時的和平滑的,當(dāng)用戶在物理屏幕上拖動屏幕圖像時,用戶感覺屏幕圖像是附著在他們的手指上的。
通過使用布局來滾動,F(xiàn)lutter可以實現(xiàn)高級類型的滾動,如下所示。注意這些都是GIF動畫圖像,F(xiàn)lutter更平滑。你可以(也應(yīng)該)自己運行這些應(yīng)用程序;請參閱本文末尾的參考資料部分。
Flutter Gallery appPosse Gallery appPosse Gallery app
在大多數(shù)情況下,F(xiàn)lutter可以一次完成布局,這意味著在線性時間內(nèi)完成布局,因此它可以處理大量小部件。Flutter還可以進(jìn)行緩存和其他操作,因此它可以在可能的情況下完全避免布局。
自定義設(shè)計
因為小部件現(xiàn)在是應(yīng)用程序的一部分,所以可以添加新的小部件,并定制現(xiàn)有的小部件,使其具有不同的外觀或感覺,或與公司的品牌相匹配。移動設(shè)計的趨勢已經(jīng)不再是幾年前常見的千篇一律的應(yīng)用程序,而是轉(zhuǎn)向取悅用戶并贏得獎項的定制設(shè)計。
Flutter為Android、iOS和材料設(shè)計提供了豐富的、可定制的小部件集(事實上,我們聽說Flutter有著最精確的材料設(shè)計)。我們使用Flutter的可定制性來構(gòu)建這些小部件集,以匹配多個平臺上本機小部件的外觀。應(yīng)用程序開發(fā)人員可以使用相同的可定制性來進(jìn)一步調(diào)整小部件以滿足他們的需求。
再談?wù)劷换バ砸晥D
用于響應(yīng)web視圖的庫引入了virtual DOM。DOM是HTML文檔對象模型,是JavaScript用來操作HTML文檔的API,表示為元素樹。virtual DOM是使用編程語言(在本例中是JavaScript)中的對象創(chuàng)建的DOM的抽象版本。
在響應(yīng)式web視圖中(由諸如ReactJS等系統(tǒng)實現(xiàn)),virtual DOM是不可變的,每次發(fā)生變化都要從頭開始重建。
將virtual DOM與實際DOM進(jìn)行比較,以生成一組最小的更改,然后執(zhí)行這些更改來更新實際DOM。
最后,平臺重新呈現(xiàn)真實的DOM并將其繪制到畫布中。
這聽起來可能需要大量額外的工作,但這是非常值得的,因為操作HTML DOM非常代價非常高昂。
React Native也做了類似的事情,不過是針對移動應(yīng)用。它在移動平臺上操作本地小部件,而不是DOM。它不是一個虛擬DOM,而是構(gòu)建一個小部件的虛擬樹,并將其與本機小部件進(jìn)行比較,只更新那些已經(jīng)更改的小部件。
請記住,React Native必須通過橋與本機小部件進(jìn)行通信,因此虛擬小部件樹有助于將橋上的傳遞保持在最低限度,同時仍然允許使用本機小部件。最后,一旦本地小部件被更新,平臺就會將它們呈現(xiàn)給畫布。
React Native是移動開發(fā)的一大勝利,也是Flutter的靈感來源,但Flutter更進(jìn)一步。
回想一下,在Flutter中,小部件和渲染器已經(jīng)從平臺提升到用戶的應(yīng)用程序中。由于沒有本地平臺小部件可操作,所以原來的虛擬小部件樹現(xiàn)在變成了小部件樹。Flutter呈現(xiàn)小部件樹并將其繪制到平臺畫布。這很好,很簡單(而且很快)。此外,動畫發(fā)生在用戶空間中,因此應(yīng)用程序(以及開發(fā)人員)對它有更多的控制。
Flutter渲染器本身很有趣:它使用幾個內(nèi)部樹結(jié)構(gòu)只渲染那些需要在屏幕上更新的小部件。例如,渲染器使用“使用合成的結(jié)構(gòu)重繪”(“結(jié)構(gòu)”的意思是通過小部件,這比通過屏幕上的矩形區(qū)域更有效)。未更改的小部件,即使是那些已經(jīng)移動的小部件,也會從緩存中進(jìn)行“位傳輸(bit blit)”,這非常快。這是使?jié)L動在抖動中表現(xiàn)得如此出色的原因之一,即使是在高級滾動中(如上所述)。
Dart 編程語言
因為Flutter與其他使用響應(yīng)視圖的系統(tǒng)一樣, 為每個新幀刷新視圖樹,它創(chuàng)建了許多僅存活一幀(六十分之一秒)的對象。并且,Dart使用對于這類系統(tǒng)非常有效的“分代垃圾收集技術(shù)”,因為這樣做可以降低回收對象(特別是短命的對象)的消耗。此外,Dart僅使用單個指針的增減便能完成對象的分配,這種指針運作很快并且不需要鎖定。這有助于避免UI丟幀和卡頓。
Dart還有一個“ tree shaking ”編譯器,它只包含你的應(yīng)用程序所需的代碼。您可以放心地使用大型小部件庫,即使您只會用到庫中的一個或兩個小部件。有關(guān)Dart的更多信息,請閱讀“ 為什么Flutter使用Dart ”。
實時重載
Flutter最受歡迎的原因之一就是其快速且有狀態(tài)顯示的實時重新加載功能。您可以在一個Flutter應(yīng)用程序運行時對其進(jìn)行更改,它將重新加載已更改的應(yīng)用程序代碼,并讓它從停止的地方繼續(xù)運行,通常在不到一秒鐘的時間內(nèi)。如果您的應(yīng)用程序遇到錯誤,您通常可以修復(fù)錯誤,然后繼續(xù),就像錯誤從未發(fā)生過一樣。即使你必須做一個完全重新加載,它依舊是很快的。
開發(fā)者們告訴我們這讓他們“畫”出他們自己的應(yīng)用程序,做出一個改動并幾乎實時看到結(jié)果卻不用重新啟動應(yīng)用程序。
兼容性
因為小部件(包括用于小部件的渲染器)是應(yīng)用程序的一部分,而不是平臺的一部分,所以無需“適配鏈接庫(Compact libraries)”。 您的應(yīng)用不僅能運行,而且能在最近的系統(tǒng)版本上正常運行(安卓4.1及IOS 8.0)。這大大減少了在舊操作系統(tǒng)版本上測試應(yīng)用程序的需求。此外,您的應(yīng)用程序很可能適用于未來的操作系統(tǒng)版本。
有一個潛在的問題是,因為Flutter不使用原生平臺的小部件,所以當(dāng)支持新小部件的新版iOS或安卓發(fā)布時,或是當(dāng)老版本的小部件的外觀和行為方式被改變時,F(xiàn)lutter小部件是否需要很長時間才能更新?
- 首先,Google是Flutter的一個重要內(nèi)部用戶,因此我們有足夠的熱情來更新小部件集以使其保持最新狀態(tài)并盡可能接近當(dāng)前新平臺的小部件。
- 就算窗口小部件遲遲不更新,F(xiàn)lutter的小部件具有很強的可擴展和可定制能力,任何人都可以更新它們,即使是你。于是,人們甚至不必提交請求,您也不必等待Flutter本身更新。
- 以上幾點僅適用于當(dāng)您希望在應(yīng)用中使用新的小部件時。如果您不希望更改影響應(yīng)用的外觀或行為方式,同樣也是可以的。窗口小部件是您應(yīng)用的一部分,因此窗口小部件永遠(yuǎn)不會在您不知情的情況下更改并使您的應(yīng)用看起來很糟糕(或者更糟糕的是,導(dǎo)致應(yīng)用無法運行)。
- 此外,您可以通過自行編寫小部件,以便即使在較舊的OS版本上也可以使用新的小部件。
其他優(yōu)點
Flutter的簡單性使它變得更快,同時它具有普遍的可定制性和可擴展性,使其功能強大。
Dart有一個軟件包存儲庫,因此您可以擴展應(yīng)用程序的功能。例如,有許多軟件包可以輕松訪問Firebase,因此您可以構(gòu)建“無服務(wù)器”應(yīng)用程序。外部貢獻(xiàn)者創(chuàng)建了一個包,允許您訪問Redux數(shù)據(jù)存儲。還有一些稱為“ plugins(插件)”的軟件包,可以以獨立于操作系統(tǒng)的方式,更輕松地訪問平臺服務(wù)和硬件,例如 加速度計或攝像頭。
當(dāng)然,F(xiàn)lutter也是開源的,再加上Flutter渲染堆棧是你應(yīng)用程序的一部分,這意味著你可以為個人應(yīng)用程序自定義幾乎任何你想要的東西。此圖中的所有綠色都可以自定義:
所以,F(xiàn)lutter到底新在哪,為何如此吸引人
如果有人像這樣問你,現(xiàn)在你知道該如何回答它們了:
- 響應(yīng)式視圖的優(yōu)點,不用JavaScript的橋接
- 快速,流暢,可預(yù)測; 代碼將AOT編譯為本機(ARM)代碼
- 開發(fā)人員可以完全控制小部件和布局
- 配有漂亮的可定制小部件
- 出色的開發(fā)工具,具有驚人的實時重載功能
- 性能更高,兼容性更強,更有趣
你注意到我遺漏了什么嗎?其實那是人們在談?wù)揊lutter時首先提到的東西,但對我而言,這是Flutter最無趣的事情之一。
事實上,F(xiàn)lutter可以從單個代碼庫為多個平臺構(gòu)建漂亮而快速的應(yīng)用程序。當(dāng)然,它本身就是為此而生的!它的可定制性和可擴展性,可以輕松地將Flutter定位到多個平臺,而不會放棄性能或功耗。
革命性
我也從未完全解釋為什么Flutter是“革命性的”。但這樣解釋起來很合適,因為外部開發(fā)人員使用Flutter構(gòu)建的第一個主要應(yīng)用程序之一是“ 漢密爾頓:美國音樂劇 ” 的官方應(yīng)用程序,它發(fā)生在美國獨立戰(zhàn)爭時期。漢密爾頓是有史以來最受歡迎的百老匯音樂劇之一。
項目經(jīng)理Posse表示,他們選擇了Flutter,因為他們需要“ 在短短的三個月內(nèi) ” 構(gòu)建應(yīng)用程序。他們稱之為“為革命性的演出創(chuàng)建革命性的應(yīng)用”,并稱“Flutter是美麗,高性能,品牌驅(qū)動的移動體驗的絕佳選擇?!?nbsp;他們還在 Google Developer Days會議上就他們構(gòu)建Flutter的應(yīng)用程序的體驗發(fā)表了講話。該應(yīng)用程序可在Android和iOS上使用,并獲得好評如潮。
一起投身變革吧
2018年12月4日,Flutter 1.0發(fā)布。2021年3月4日,F(xiàn)lutter 2.0 發(fā)布,Google 將繼續(xù)為其添加更多功能,并且計劃進(jìn)行更多優(yōu)化。Flutter的使用已經(jīng)開始,全球有超過250,000名開發(fā)人員。Flutter目前在Github上活躍的軟件存儲庫中排名前20位。
如果您對Flutter感興趣,可以安裝它并使用安裝附帶的一些示例應(yīng)用程序。一定要查看有狀態(tài)顯示的實時重載。
如果您不是開發(fā)人員或只是想看一些應(yīng)用程序,您可以安裝使用Flutter構(gòu)建的應(yīng)用程序,并查看它們的外觀和性能。我推薦Hamilton應(yīng)用程序,但還有其他優(yōu)秀的程序?;蛘吣€可以觀看來自Google I / O的視頻。
資源
- 觀看來自Google I / O 2018的Flutter視頻
- 觀看2018年 1月23日至24日在加利福尼亞州洛杉磯舉行的DartConf 2018的視頻
- 介紹Flutter的視頻。
網(wǎng)站:
- The Flutter website
- The source repositories (pull requests welcome!)
- More helpful links
- Gitter channel
視頻:
- Experience building the Hamilton app, at GDD
- Live coding a Flutter app, at Google I/O
- Live coding with a designer, at Google I/O
- “Flutter, a new hope” at Droidcon Italy
- “The Flutter rendering pipeline”
應(yīng)用:
- The app for Hamilton: An American Musical
- Flutter Gallery: for Android, on Github (also included in the flutter install at examples/flutter_gallery)
- Posse Gallery
- Friendlychat: first codelab, Firebase codelab, on Github