Flutter 的革命之處

Junyiii發表於2017-12-20

翻譯原文連結

什麼是Flutter?

Flutter移動應用程式SDK是一種構建快速,美觀的移動應用程式的新方式,可幫助開發人員擺脫過去常見的“cookie切割”應用程式。 試過Flutter的人真的喜歡它; 例如,看這個這個,或者這個。 或者,這是第三方編輯的文章和視訊列表

就像任何新的系統一樣,人們想知道Flutter的不同,或者換句話說,“Flutter有什麼新鮮和令人興奮的東西?”這是一個公平的問題,本文將從技術角度來回答它 - 而不是 只是什麼是令人興奮的,但為什麼。 但是,首先,有一點歷史。

移動應用程式開發的簡要歷史

移動應用程式開發是一個相對較新的領域。 第三方開發人員已經能夠在不到十年的時間內開發移動應用程式,所以工具仍在不斷髮展並不奇怪。

OEM SDKs

Apple iOS SDK於2008年釋出,2009年釋出Google Android SDK。這兩個SDK分別基於不同的語言:Objective-C和Java。

Flutter 的革命之處
您的應用程式會與平臺進行交談,以建立widgets或訪問相機等服務。 widgets呈現給螢幕畫布,並且事件被傳回給widgets。 這是一個簡單的架構,但是您幾乎必須為每個平臺建立單獨的應用程式,因為這些widgets是不同的,更不用說語言。

WebView

第一個跨平臺框架基於JavaScript和WebViews。 例如Titanium和一系列相關的框架:PhoneGap,Apache Cordova,Ionic等等。 在蘋果釋出iOS SDK之前,他們鼓勵第三方開發者為iPhone構建webapps,所以用web技術構建跨平臺的應用程式是一個顯而易見的步驟。

Flutter 的革命之處
您的應用程式建立HTML並將其顯示在平臺上的WebView中。 請注意,像JavaScript這樣的語言很難直接與原生程式碼(like thee services)交談,所以它們會經歷一個在JavaScrip領域和Native 領域之間進行上下文切換的“Bridge”。 因為平臺服務通常不是經常被呼叫的,所以這不會導致太多的效能問題。

Reactive Views

ReactJS(和其他)這樣的響應式Web框架已經變得流行,主要是因為它們通過使用從響應式程式設計中借用的程式設計模式來簡化Web檢視的建立。 2015年,建立了React Native將響應式檢視的諸多好處帶給移動應用程式。

Flutter 的革命之處
React Native非常受歡迎(並且是值得的),但是由於JavaScript領域訪問Native領域的OEM widgets,因此它也必須通過這個橋樑。 通常訪問widgets的頻率非常高(在動畫,轉換過程中,或者使用者用手指在螢幕上滑動某些東西時,每秒可達60次),因此可能會導致效能問題。 正如一篇關於React Native的文章所說:

這裡是理解React Native效能的主要關鍵之一。 每個領域本身都非常快。 當我們從一個領域轉移到另一個時,效能瓶頸往往會發生。 為了構建高效能的React Native應用程式,我們必須保持橋樑通過最低限度。

Flutter

像React Native一樣,Flutter也提供響應式風格的檢視。 Flutter使用編譯的程式語言即Dart的方法來避免JavaScript橋引起的效能問題,。 Dart被“提前編譯”(AOT)編譯成多個平臺的原生程式碼。 這使得Flutter可以與平臺進行通訊,而無需通過執行了上下文切換的JavaScript Bridge。 編譯為本機程式碼也可以提高應用程式的啟動時間。 Flutter是唯一提供響應式檢視而不需要JavaScript Bridge的移動SDK的事實應該足以讓Flutter變得有趣並且值得嘗試,但是Flutter還有一些更具革命性的地方,那就是它如何實現widgets。

Widgets

Widgets是影響和控制應用程式的檢視和介面的元素。 說Widgets是移動應用程式最重要的部分之一,這並不是誇大其詞。 事實上,Widgets可以成就或挫敗一個應用程式。

Flutter 的革命之處

  • Widgets的外觀和感覺是最重要的。 Widgets需要看起來不錯,包括各種螢幕尺寸。 他們也需要感覺自然。
  • Widgets必須快速執行:建立Widgets樹,inflate the Widgets(例項化他們的子項),將它們放在螢幕上,渲染它們,或者(特別是)使它們動畫化。
  • 對於現代應用程式,Widgets應該是可擴充套件的和可定製的。 開發人員希望能夠新增令人愉快的新Widgets,並自定義所有Widgets以匹配應用程式的品牌。

Flutter有一個新的架構,包括外觀和感覺不錯,快速,可定製和可擴充套件的Widgets。 沒錯,Flutter不使用OEM Widgets(或DOM WebViews),它提供了自己的Widgets。

Flutter 的革命之處

Flutter將Widgets和渲染器從平臺移動到應用程式中,從而使其可以自定義和擴充套件。 Flutter對平臺的需求平臺是一個畫布,在這個畫布中,Widgets可以呈現在裝置螢幕上,並可以訪問事件(觸控,定時器等)和服務(位置,攝像機等)。 Dart程式(綠色)和本地平臺程式碼(iOS或Android藍色)之間仍然存在一個介面,可以進行資料編碼和解碼,但這可能比JavaScript Bridge 快幾個數量級。

將Widgets和渲染器移動到應用程式中會影響應用程式的大小。 Android上Flutter應用程式的最小大小約為6.7MB,與使用類似工具構建的最小應用程式類似。 由您決定是否Flutter的好處是值得的權衡,所以本文的其餘部分討論這些好處。

佈局

Flutter最大的改進之一就是它的佈局。佈局根據一組規則(也稱為約束)來確定widgets的大小和位置。 傳統上,佈局使用一堆可應用於(虛擬)任何widgets的規則。規則實現了多種佈局方法。讓我們以CSS佈局為例,因為它是眾所周知的(儘管和Android和iOS的佈局基本相似)。 CSS具有屬性(規則),這些屬性應用於HTML元素(widgets)。 CSS3定義了375個屬性。 CSS包含許多佈局模型,包括(多個)框模型,浮動元素,表格,多列文字,分頁媒體等等。其他的佈局模型,如flexbox和grid,後來被新增,因為開發人員和設計師需要更多的控制佈局,並使用表和透明影像來獲得他們想要的。在傳統佈局中,開發人員無法新增新的佈局模型,因此必須將flexbox和網格新增到CSS並在所有瀏覽器上實施。 傳統佈局的另一個問題是規則可以相互影響(甚至相互衝突),並且元素通常應用了許多規則。這使佈局變慢。更糟的是,佈局表現通常是N階有序的,所以隨著元素數量的增加,佈局變得更加緩慢。 Flutter是由Google的Chrome瀏覽器團隊成員進行的一項實驗開始的。如果我們忽略了傳統的佈局模型,我們想看看是否可以建立更快的渲染器。幾周後,我們取得了顯著的業績增長。我們發現:

  • 大多數佈局相對簡單,比如:滾動頁面上的文字,大小和位置僅取決於顯示大小的固定矩形,以及一些表格,浮動元素等等。
  • 大多數佈局對於widgets子樹是區域性的,並且該子樹通常使用一個佈局模型,因此這些widgets只需要少量的規則支援。 我們意識到,如果我們使用如下的要點,佈局可以被大大簡化:
  • 每個widget都可以指定自己的簡單佈局模型,而不必擁有大量可應用於任何widget的佈局規則。
  • 因為每個widget都有一個小得多的佈局規則,佈局可以大大優化。
  • 為了進一步簡化佈局,我們把幾乎所有東西都變成了一個widget

這裡是Flutter程式碼來建立一個佈局簡單的widget樹:

new Center(
  child: new Column(
    children: [
      new Text('Hello, World!')),
      new Icon(Icons.star, color: Colors.green)
    ]
  )
複製程式碼

這個程式碼的語義是足夠的,你可以很容易地想象它會產生什麼,但是這裡得到的結果是:

Flutter 的革命之處

在這個程式碼中,一切都是widget,包括佈局。Center widget將其中心放置在其父級(例如螢幕)中。Column佈局widget垂直排列其子元素(widget列表)。該列包含一個文字widget和一個圖示widget(它有一個屬性,它的顏色)。 在Flutter中,居中和填充是widget。主題是widget,適用於他們的孩子。甚至應用程式和導航都是widget。 Flutter包含了很多用於佈局的widget,不僅包括列,還包括行,網格,列表等。此外,Flutter還有一個獨特的佈局模型,我們稱之為“sliver layout model”,用於滾動。 Flutter中的佈局非常快,可以用於滾動。想一想。滾動必須是瞬間發生的和平滑的,以至於使用者感覺像螢幕影像在他們拖過物理螢幕時被附著到他們的手指。 通過使用滾動佈局,Flutter可以實現高階型別的滾動,如下所示。請注意,這些動畫GIF影像,Flutter更平滑。你可以(也應該)自己執行這些應用程式;請參閱本文末尾的參考資料部分。

Flutter 的革命之處

Flutter 的革命之處

Flutter 的革命之處

大多數時候,Flutter可以一次完成佈局,這意味著線性時間,所以它可以處理大量的widgets。 Flutter也做快取和其他事情,所以可以避免佈局。

定製設計

因為widgets現在是應用程式的一部分,所以可以新增新的widgets,並且可以定製現有的widgets以使其具有不同的外觀或感覺,或匹配公司的品牌。 移動設計的趨勢遠離幾年前常見的cookie應用程式,並且朝向取悅使用者並贏得獎項的定製設計。 Flutter為Android,iOSMaterial Design提供了豐富的,可自定義的widgets集(事實上,我們已經知道,Flutter是Material Design中最高保真實現之一)。 我們使用Flutter的可定製性來構建這些widgets集,以匹配多個平臺上的本機widgets的外觀和風格。 應用程式開發人員可以使用相同的可定製性來進一步調整視窗widgets,以滿足他們的需求。

更多關於 Reactive Views

用於reactive web views的庫引入了virtual DOM。 DOM是HTML文件物件模型(HTML Document Object Model),一個使用JavaScript用來處理HTML文件的API,用一個元素樹來表示。 虛擬DOM是使用程式語言中的物件建立的DOM的抽象版本,在這種情況下是JavaScript。

在 reactive web views(由ReactJS等系統實現)中,虛擬DOM是不可變的,每當有任何變化時,都會從頭開始重建。 將虛擬DOM與真實的DOM進行比較,生成一組最小的更改,然後執行這些更改以更新真實的DOM。 最後,平臺重新渲染真實的DOM並將其繪製到畫布中。

Flutter 的革命之處

這可能聽起來是很多額外的工作,但它是非常值得的,因為操縱HTML DOM是非常昂貴的。 React Native做類似的事情,但對於移動應用程式。 它不是DOM,而是操縱移動平臺上的原生widgets。 它不是虛擬DOM,而是構建一個widgets的虛擬樹,並將其與本機widgets進行比較,只更新那些已更改的widgets。

Flutter 的革命之處

請記住,React Native必須通過Bridge與Native widgets進行通訊,因此widgets的虛擬樹有助於將Bridge過程消耗保持在最低限度,同時仍允許使用本機視窗widgets。 最後,一旦Native widgets被更新,平臺將把它們呈現在畫布上。 React Native是移動開發的一大勝利,是Flutter的靈感來源,但Flutter更進一步。

Flutter 的革命之處

回想一下,在Flutter中,widgets和渲染器已經從平臺上升到使用者的應用程式中。沒有原生的OEM widget tree可以操作,那麼virtual widget tree現在是widget tree。 Flutter渲染widget tree並將其繪製到平臺畫布上。這是很好,簡單(和快速)。另外,動畫發生在使用者空間中,所以應用程式(以及開發者)對其有更多的控制。

Flutter渲染器本身很有趣:它使用幾個內部樹結構來渲染那些需要在螢幕上更新的widgets。例如,渲染器使用“structural repainting using compositing”("structural"意味著是通過widget,比通過螢幕上的矩形區域更有效)。不變的widgets,甚至是那些已經移動的widgets,都是從快取記憶體中“bit blited”的。這是Flutter中即使在高階滾動(在上面討論和示出)中滾動如此執行的事情之一。 為了仔細瞭解Flutter渲染器,我推薦這個視訊。你也可以看看程式碼,因為Flutter是開源的。當然,您可以自定義甚至替換整個堆疊,包括渲染器,合成器,動畫,手勢識別器和(當然)widgets。

Dart程式語言

因為Flutter就像使用反應檢視的其他系統一樣,為每個新幀重新整理檢視樹,所以它建立了許多隻能存活一幀(六十分之一秒)的物件。 幸運的是,Dart使用對這類系統非常有效的“分代垃圾收集”,因為物件(尤其是短命的)相對cheap。 另外,物件的分配可以用single pointer bump來完成,這是快速的並且不需要lock。 這有助於避免UI jank和stutter。 Dart也有一個“tree shaking”的編譯器,其中只包括您的應用程式需要的程式碼。 即使只需要其中的一個或兩個,也可以使用大型widgets庫。

Hot reload

Flutter最受歡迎的功能之一是其快速,有狀態的Hot reload。 您可以在Flutter應用程式執行時對其進行更改,並重新載入已更改的應用程式的程式碼,並讓程式碼從停止的位置繼續,通常不到一秒鐘。 如果您的應用程式遇到錯誤,您通常可以修復錯誤,然後繼續,如同錯誤從未發生過。 即使你必須做一個完整的過載,速度也很快。

Flutter 的革命之處

開發人員告訴我們,這可以讓他們“繪製”他們的應用程式,一次做出一個更改,然後幾乎立即看到結果,而不必重新啟動應用程式。

相容性

由於widgets(以及這些widgets的渲染器)是您應用程式的一部分,而不是平臺的一部分,因此不需要“相容庫”。您的應用程式不僅可以正常工作,而且在最近的作業系統版本(Android Jelly Bean和更新的版本以及iOS 8.0和以上的版本)上也可以發揮同樣的作用。這大大減少了在較舊的OS版本上測試應用程式的需要。另外,您的應用很可能會在未來的作業系統版本上執行。 我們被問到一個潛在的問題。由於Flutter不使用OEM native widgets,當新版本的iOS或Android支援新型別的OEM native widgets或更改現有OEM native widgets的外觀或行為時,Flutter widgets 是否需要更新才會更新?

  • 首先,Google是Flutter的內部使用者,所以我們有強烈的動機去更新這些Widget集合,以保持它們的當前狀態,並儘可能接近當前的OEMwidgets。
  • 如果有一段時間我們在更新widget時速度太慢,那麼Google並不是Flutter的唯一有激勵讓widget保持最新狀態的使用者。 Flutter的widgets是可擴充套件和可定製的,任何人都可以更新它們,甚至是你。甚至不必提交一個拉請求。你永遠不用等待Flutter本身的更新。
  • 以上幾點僅適用於您希望在應用程式中反映新的變化。如果您不希望更改影響您的應用的外觀或行為方式,那就太好了。widget是你的應用程式的一部分,所以一個widget將永遠不會在你的操作外發生改變,使你的應用程式看起來不好(或更糟的是,打破你的應用程式)。
  • 作為一個額外的好處,你可以編寫你的應用程式,使它使用新的widget甚至在舊的作業系統版本中。

其他Benifits

Flutter的簡單性使其變得更加快速,但是普遍的可定製性和可擴充套件性使其變得強大。 Dart有一個軟體包的儲存庫,所以你可以擴充套件你的應用程式的功能。 例如,有許多軟體包可以輕鬆訪問Firebase,因此您可以構建“serverless”應用程式。 外部貢獻者已經建立了一個包,允許您訪問Redux資料儲存。 還有一些名為“plugins”的軟體包,可以以獨立於作業系統的方式輕鬆訪問平臺服務和硬體,如加速度計或攝像頭。

當然,Flutter也是開源的,加上Flutter渲染棧是你的應用程式的一部分,意味著你可以自定義幾乎任何你想要的一個單獨的應用程式。 這個圖中的所有綠色都可以定製:

Flutter 的革命之處

所以,“Flutter有什麼新的和令人興奮的?”

如果有人問你有關Flutter,現在你知道如何回答他們:

  • 反應式檢視的優點,沒有JavaScript Bridge
  • 快速,流暢,可預測; 程式碼將AOT編譯為本機(ARM)程式碼
  • 開發人員可以完全控制widgets和佈局
  • 帶有漂亮,可定製的widgets
  • 極好的的開發人員工具,驚人的hot reload
  • 效能更高,相容性更多,更有趣

你有沒有注意到我從這個清單中刪除了什麼? 當人們談論Flutter時,這通常是人們首先提到的,但對於我來說這是Flutter最不感興趣的事情之一。 事實上,Flutter可以從一個程式碼庫為多個平臺構建美麗而快速的應用程式。 當然,這應該是一個給定的! 這是可定製和可擴充套件性,可以輕鬆地將Flutter目標鎖定到多個平臺,而不會放棄效能或功耗。

翻譯原文連結

相關文章