翻譯原文連接html
Flutter移動應用程序SDK是一種構建快速,美觀的移動應用程序的新方式,可幫助開發人員擺脫過去常見的「cookie切割」應用程序。 試過Flutter的人真的喜歡它; 例如,看這個,這個,或者這個。 或者,這是第三方編輯的文章和視頻列表。react
就像任何新的系統同樣,人們想知道Flutter的不一樣,或者換句話說,「Flutter有什麼新鮮和使人興奮的東西?」這是一個公平的問題,本文將從技術角度來回答它 - 而不是 只是什麼是使人興奮的,但爲何。 可是,首先,有一點歷史。android
移動應用程序開發是一個相對較新的領域。 第三方開發人員已經可以在不到十年的時間內開發移動應用程序,因此工具仍在不斷髮展並不奇怪。git
Apple iOS SDK於2008年發佈,2009年發佈Google Android SDK。這兩個SDK分別基於不一樣的語言:Objective-C和Java。github
您的應用程序會與平臺進行交談,以建立widgets或訪問相機等服務。 widgets呈現給屏幕畫布,而且事件被傳回給widgets。 這是一個簡單的架構,可是您幾乎必須爲每一個平臺建立單獨的應用程序,由於這些widgets是不一樣的,更不用說語言。第一個跨平臺框架基於JavaScript和WebViews。 例如Titanium和一系列相關的框架:PhoneGap,Apache Cordova,Ionic等等。 在蘋果發佈iOS SDK以前,他們鼓勵第三方開發者爲iPhone構建webapps,因此用web技術構建跨平臺的應用程序是一個顯而易見的步驟。web
您的應用程序建立HTML並將其顯示在平臺上的WebView中。 請注意,像JavaScript這樣的語言很難直接與本地代碼(like thee services)交談,因此它們會經歷一個在JavaScrip領域和Native 領域之間進行上下文切換的「Bridge」。 由於平臺服務一般不是常常被調用的,因此這不會致使太多的性能問題。像ReactJS(和其餘)這樣的響應式Web框架已經變得流行,主要是由於它們經過使用從響應式編程中借用的編程模式來簡化Web視圖的建立。 2015年,建立了React Native將響應式視圖的諸多好處帶給移動應用程序。編程
React Native很是受歡迎(而且是值得的),可是因爲JavaScript領域訪問Native領域的OEM widgets,所以它也必須經過這個橋樑。 一般訪問widgets的頻率很是高(在動畫,轉換過程當中,或者用戶用手指在屏幕上滑動某些東西時,每秒可達60次),所以可能會致使性能問題。 正如 一篇關於React Native的文章所說:這裏是理解React Native性能的主要關鍵之一。 每一個領域自己都很是快。 當咱們從一個領域轉移到另外一個時,性能瓶頸每每會發生。 爲了構建高性能的React Native應用程序,咱們必須保持橋樑經過最低限度。redux
像React Native同樣,Flutter也提供響應式風格的視圖。 Flutter使用編譯的編程語言即Dart的方法來避免JavaScript橋引發的性能問題,。 Dart被「提早編譯」(AOT)編譯成多個平臺的本地代碼。 這使得Flutter能夠與平臺進行通訊,而無需經過執行了上下文切換的JavaScript Bridge。 編譯爲本機代碼也能夠提升應用程序的啓動時間。 Flutter是惟一提供響應式視圖而不須要JavaScript Bridge的移動SDK的事實應該足以讓Flutter變得有趣而且值得嘗試,可是Flutter還有一些更具革命性的地方,那就是它如何實現widgets。react-native
Widgets是影響和控制應用程序的視圖和界面的元素。 說Widgets是移動應用程序最重要的部分之一,這並非誇大其詞。 事實上,Widgets能夠成就或挫敗一個應用程序。瀏覽器
Flutter有一個新的架構,包括外觀和感受不錯,快速,可定製和可擴展的Widgets。 沒錯,Flutter不使用OEM Widgets(或DOM WebViews),它提供了本身的Widgets。
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瀏覽器團隊成員進行的一項實驗開始的。若是咱們忽略了傳統的佈局模型,咱們想看看是否能夠創建更快的渲染器。幾周後,咱們取得了顯着的業績增加。咱們發現:
這裏是Flutter代碼來建立一個佈局簡單的widget樹:
new Center(
child: new Column(
children: [
new Text('Hello, World!')),
new Icon(Icons.star, color: Colors.green)
]
)
複製代碼
這個代碼的語義是足夠的,你能夠很容易地想象它會產生什麼,可是這裏獲得的結果是:
在這個代碼中,一切都是widget,包括佈局。Center widget將其中心放置在其父級(例如屏幕)中。Column佈局widget垂直排列其子元素(widget列表)。該列包含一個文本widget和一個圖標widget(它有一個屬性,它的顏色)。 在Flutter中,居中和填充是widget。主題是widget,適用於他們的孩子。甚至應用程序和導航都是widget。 Flutter包含了不少用於佈局的widget,不只包括列,還包括行,網格,列表等。此外,Flutter還有一個獨特的佈局模型,咱們稱之爲「sliver layout model」,用於滾動。 Flutter中的佈局很是快,能夠用於滾動。想想。滾動必須是瞬間發生的和平滑的,以致於用戶感受像屏幕圖像在他們拖過物理屏幕時被附着到他們的手指。 經過使用滾動佈局,Flutter能夠實現高級類型的滾動,以下所示。請注意,這些動畫GIF圖像,Flutter更平滑。你能夠(也應該)本身運行這些應用程序;請參閱本文末尾的參考資料部分。
大多數時候,Flutter能夠一次完成佈局,這意味着線性時間,因此它能夠處理大量的widgets。 Flutter也作緩存和其餘事情,因此能夠避免佈局。
由於widgets如今是應用程序的一部分,因此能夠添加新的widgets,而且能夠定製現有的widgets以使其具備不一樣的外觀或感受,或匹配公司的品牌。 移動設計的趨勢遠離幾年前常見的cookie應用程序,而且朝向取悅用戶並贏得獎項的定製設計。 Flutter爲Android,iOS和Material Design提供了豐富的,可自定義的widgets集(事實上,咱們已經知道,Flutter是Material Design中最高保真實現之一)。 咱們使用Flutter的可定製性來構建這些widgets集,以匹配多個平臺上的本機widgets的外觀和風格。 應用程序開發人員可使用相同的可定製性來進一步調整窗口widgets,以知足他們的需求。
用於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並將其繪製到畫布中。
這可能聽起來是不少額外的工做,但它是很是值得的,由於操縱HTML DOM是很是昂貴的。 React Native作相似的事情,但對於移動應用程序。 它不是DOM,而是操縱移動平臺上的原生widgets。 它不是虛擬DOM,而是構建一個widgets的虛擬樹,並將其與本機widgets進行比較,只更新那些已更改的widgets。
請記住,React Native必須經過Bridge與Native widgets進行通訊,所以widgets的虛擬樹有助於將Bridge過程消耗保持在最低限度,同時仍容許使用本機窗口widgets。 最後,一旦Native widgets被更新,平臺將把它們呈如今畫布上。 React Native是移動開發的一大勝利,是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。
由於Flutter就像使用反應視圖的其餘系統同樣,爲每一個新幀刷新視圖樹,因此它建立了許多隻能存活一幀(六十分之一秒)的對象。 幸運的是,Dart使用對這類系統很是有效的「分代垃圾收集」,由於對象(尤爲是短命的)相對cheap。 另外,對象的分配能夠用single pointer bump來完成,這是快速的而且不須要lock。 這有助於避免UI jank和stutter。 Dart也有一個「tree shaking」的編譯器,其中只包括您的應用程序須要的代碼。 即便只須要其中的一個或兩個,也可使用大型widgets庫。
Flutter最受歡迎的功能之一是其快速,有狀態的Hot reload。 您能夠在Flutter應用程序運行時對其進行更改,並從新加載已更改的應用程序的代碼,並讓代碼從中止的位置繼續,一般不到一秒鐘。 若是您的應用程序遇到錯誤,您一般能夠修復錯誤,而後繼續,如同錯誤從未發生過。 即便你必須作一個完整的重載,速度也很快。
開發人員告訴咱們,這可讓他們「繪製」他們的應用程序,一次作出一個更改,而後幾乎當即看到結果,而沒必要從新啓動應用程序。
因爲widgets(以及這些widgets的渲染器)是您應用程序的一部分,而不是平臺的一部分,所以不須要「兼容庫」。您的應用程序不只能夠正常工做,並且在最近的操做系統版本(Android Jelly Bean和更新的版本以及iOS 8.0和以上的版本)上也能夠發揮一樣的做用。這大大減小了在較舊的OS版本上測試應用程序的須要。另外,您的應用極可能會在將來的操做系統版本上運行。 咱們被問到一個潛在的問題。因爲Flutter不使用OEM native widgets,當新版本的iOS或Android支持新類型的OEM native widgets或更改現有OEM native widgets的外觀或行爲時,Flutter widgets 是否須要更新纔會更新?
Flutter的簡單性使其變得更加快速,可是廣泛的可定製性和可擴展性使其變得強大。 Dart有一個軟件包的存儲庫,因此你能夠擴展你的應用程序的功能。 例如,有許多軟件包能夠輕鬆訪問Firebase,所以您能夠構建「serverless」應用程序。 外部貢獻者已經建立了一個包,容許您訪問Redux數據存儲。 還有一些名爲「plugins」的軟件包,能夠以獨立於操做系統的方式輕鬆訪問平臺服務和硬件,如加速度計或攝像頭。
固然,Flutter也是開源的,加上Flutter渲染棧是你的應用程序的一部分,意味着你能夠自定義幾乎任何你想要的一個單獨的應用程序。 這個圖中的全部綠色均可以定製:
若是有人問你有關Flutter,如今你知道如何回答他們:
你有沒有注意到我從這個清單中刪除了什麼? 當人們談論Flutter時,這一般是人們首先提到的,但對於我來講這是Flutter最不感興趣的事情之一。 事實上,Flutter能夠從一個代碼庫爲多個平臺構建美麗而快速的應用程序。 固然,這應該是一個給定的! 這是可定製和可擴展性,能夠輕鬆地將Flutter目標鎖定到多個平臺,而不會放棄性能或功耗。