Flutter是一款移動應用程序SDK,一份代碼能夠同時生成iOS和Android兩個高性能、高保真的應用程序。 Flutter目標是使開發人員可以交付在不一樣平臺上都感受天然流暢的高性能應用程序。咱們兼容滾動行爲、排版、圖標等方面的差別。 在全世界,Flutter正在被愈來愈多的開發者和組織使用,而且Flutter是徹底免費、開源的。 node
說到Flutter,可能不少小夥伴都會覺得它是新興的的移動開發框架,其實否則,Flutter的歷史最先能夠追溯到2014年10月,其前身是Google內部孵化的Sky項目。git
不過,隨着Flutter熱度的上升,特別是2018年Flutter陸續發佈了Beta版和Flutter1.0,給不少小夥伴形成了一個誤區:認爲Flutter是最近新興的一個開發框架。最近,Google又發佈了1.2正式版,而且官方也發佈了今年的開發路線(參考Flutter 2019 產品路線圖),能夠預見,Flutter將在2019年迎來真正的爆發和成長。 github
相比React Native和Weex,Flutter實現跨平臺採用了更爲完全的方案(參考移動跨平臺技術方案總結)。它既沒有采用WebView也沒有采用JavaScript,而是本身實現了一臺UI框架,而後直接系統更底層渲染系統上畫UI。因此它採用的開發語言不是JS,而Dart(Dart是面向對象的、類定義的、單繼承的語言。它的語法相似C語言,能夠轉譯爲JavaScript,支持接口(interfaces)、混入(mixins)、抽象類(abstract classes)、具體化泛型(reified generics)、可選類型(optional typing)和sound type syste)。 據稱Dart語言能夠編譯成原生代碼,直接跟原生通訊,其原理模型圖以下: web
同時,Flutter將UI組件和渲染器從平臺移動到應用程序中,這使得它們能夠自定義和可擴展。Flutter惟一要求系統提供的是canvas,以便定製的UI組件能夠出如今設備的屏幕上,以及訪問事件(觸摸,定時器等)和服務(位置、相機等)。這是Flutter能夠作到跨平臺並且高效的關鍵。另外Flutter學習了RN的UI編程方式,引入了狀態機,更新UI時只更新最小改變區域。macos
系統的UI框架能夠取代,可是系統提供的一些服務是沒法取代的。Flutter在跟系統service通訊方式,採用的是一種相似插件式的方式,或者有點像遠程過程調用RPC方式,這種方式聽說也要比RN的橋接方式高效。關於RN和Flutter到底誰更優秀,有興趣的讀者能夠關注下官方的撕逼大戰React Native 團隊怎麼看待 Flutter 的。編程
React-Native、Weex 核心是經過 Javascript 開發,執行時須要 Javascript 解釋器,UI 是經過原生控件渲染。Flutter 與用於構建移動應用程序的其它大多數框架不一樣,由於 Flutter 既不使用 WebView,也不使用操做系統的原生控件。 相反,Flutter 使用本身的高性能渲染引擎來繪 制 widget。Flutter 使用 C、C ++、Dart 和 Skia(2D渲染引擎)構建。 canvas
Skia 是一個 2D的繪圖引擎庫,其前身是一個向量繪圖軟件,Chrome 和 Android 均採用 Skia 做爲繪圖引擎。Android 自帶了 Skia,因此 Flutter Android SDK要比 iOS SDK小不少。瀏覽器
在 ReactNative 中,引入了虛擬 DOM 來減小DOM的迴流和重繪,系統將虛擬 DOM 與真正的 DOM 進行比較,生成一組最小的更改,而後執行這些更改,以更新真正的 DOM。最後,平臺從新繪製真實的 DOM 到畫布中。bash
React Native 是移動開發的一大進步,而且是 Flutter 的靈感來源,但 Flutter 更進一步。 在 Flutter 中,UI 組件和渲染器已經從平臺中集成到用戶的應用程序中。沒有系統 UI 組件能夠操做,因此原來虛擬控件樹的地方如今是真實的控件樹,Flutter 渲染 UI 控件樹並將其繪製到平臺畫布上。服務器
若是說非要比較 Flutter 和 React Native的優點,能夠參考下面幾點:
Flutter 由於是本身作的渲染,所以在iOS和Android的效果基本徹底一致。 React Native存在將RN控件轉換爲對應平臺原生控件的過程,存在必定的差別(如以前在調研裏提到過的Button在iOS和Android下面顯示效果不同)。
Flutter使用的Dart語言,支持AOT和JIT兩種模式,在Dev時候,經過JIT能夠實現熱重載,開發者能夠即時的看到代碼修改的效果。而在Release Build的時候,經過AOT事先編譯,來最大化的優化性能。所以目前Flutter不支持代碼的熱更新,不過在Flutter 2019 產品路線圖)能夠看到這方面的消息。
ReactNative 的代碼經過加載 JSBundle.js執行,JSBundle.js能夠保存在本地,也能夠經過遠程加載。目前有不少RN的熱更新方案供選擇。
Flutter iOS空項目 30M左右,Android空項目 7M左右。 (iOS須要額外集成Skia) React Native iOS空項目 3M左右,Android20M左右。(Android會加入OKHttp致使體積增大)
Flutter 部分的底層功能在 Android 系統上已經有實現,所以 Android 上適配要好(RN在 Android 上有可能遇到兼容性問題)。
運行效率上,Flutter和ReactNative均可以達到理論上的60幀的刷新率,來實現「Native般的流暢體驗」,Flutter是全Native在執行,基於底層代碼(Android 上爲 C++ with NDK,iOS 上爲 C++ with LLVM),而ReactNative是Native控件 + JavaScript代碼,實際性能上,Flutter應該優於ReactNative,據官方文檔,Flutter能夠在支持的設備上達到120FPS,而ReactNative的文檔上,只提到了能夠達到60FPS。
兼容性上,Flutter 提供的 widget 都是基於 skia來實現和精心定製的,與具體平臺沒關,因此能保持很高的跨 os 跨 os version 的兼容性。 Flutter 從更基礎的層去抹平平臺差別,站在了更寬廣、更可控的一個基礎平臺上去演變和發展。 Flutter 官方提供了大部分 Material Design 控件的實現(甚至比 Android Design Support 實現的更多)。
學習Flutter就不得不提到Dart,那Flutter和Dart有什麼關係?確實有關係,早期的Flutter團隊評估了十多種語言,並選擇了Dart,由於它符合他們構建用戶界面的方式,讀者能夠去八卦下爲何要使用Dart語言的推文。
Dart能成爲Flutter不可或缺的一部分,根本緣由仍是由於其具備如下特性:
歷史上,計算機語言分爲兩組:靜態語言(例如,Fortran和C,其中變量類型是在編譯時靜態指定的)和動態語言(例如,Smalltalk和JavaScript,其中變量的類型能夠在運行時改變)。靜態語言一般編譯成目標機器的本地機器代碼(或彙編代碼)程序,該程序在運行時直接由硬件執行。動態語言由解釋器執行,不產生機器語言代碼。
固然,事情後來變得複雜得多。虛擬機(VM)的概念開始流行,它其實只是一個高級的解釋器,用軟件模擬硬件設備。虛擬機使語言移植到新的硬件平臺更容易。所以,VM的輸入語言經常是中間語言。例如,一種編程語言(如Java)被編譯成中間語言(字節碼),而後在VM(JVM)中執行。
另外,如今有即時(JIT)編譯器。JIT編譯器在程序執行期間運行,即時編譯代碼。原先在程序建立期間(運行時以前)執行的編譯器如今稱爲AOT編譯器。
通常來講,只有靜態語言才適合AOT編譯爲本地機器代碼,由於機器語言一般須要知道數據的類型,而動態語言中的類型事先並不肯定。所以,動態語言一般被解釋或JIT編譯。
在開發過程當中AOT編譯,開發週期(從更改程序到可以執行程序以查看更改結果的時間)老是很慢。可是AOT編譯產生的程序能夠更可預測地執行,而且運行時不須要停下來分析和編譯。AOT編譯的程序也更快地開始執行(由於它們已經被編譯)。
相反,JIT編譯提供了更快的開發週期,但可能致使執行速度較慢或時快時慢。特別是,JIT編譯器啓動較慢,由於當程序開始運行時,JIT編譯器必須在代碼執行以前進行分析和編譯。研究代表,若是開始執行須要超過幾秒鐘,許多人將放棄應用。
在創造Dart以前,Dart團隊成員在高級編譯器和虛擬機上作了開創性的工做,包括動態語言(如JavaScript的V8引擎和Smalltalk的Strongtalk)以及靜態語言(如用於Java的Hotspot編譯器)。他們利用這些經驗使Dart在編譯和執行方面很是靈活。
Dart是同時很是適合AOT編譯和JIT編譯的少數語言之一(也許是惟一的「主流」語言)。支持這兩種編譯方式爲Dart和(特別是)Flutter提供了顯著的優點。
JIT編譯在開發過程當中使用,編譯器速度特別快。而後,當一個應用程序準備發佈時,它被AOT編譯。所以,藉助先進的工具和編譯器,Dart具備一箭雙鵰的優點:極快的開發週期、快速的執行速度和極短啓動時間。
Dart在編譯和執行方面的靈活性並不止於此。例如,Dart能夠編譯成JavaScript,因此瀏覽器能夠執行。這容許在移動應用和網絡應用之間重複使用代碼。開發人員報告他們的移動和網絡應用程序之間的代碼重用率高達70%。經過將Dart編譯爲本地代碼,或者編譯爲JavaScript並將其與node.js一塊兒使用,Dart也能夠在服務器上使用。
最後,Dart還提供了一個獨立的虛擬機(本質上就像解釋器同樣),虛擬機使用Dart語言自己做爲其中間語言。
Dart能夠進行高效的AOT編譯或JIT編譯、解釋或轉譯成其餘語言。Dart編譯和執行不只很是靈活,並且速度特別快。
前面討論過一個有助於保持順暢的特性,那就是Dart能AOT編譯爲本地機器碼。預編譯的AOT代碼比JIT更具可預測性,由於在運行時不須要暫停執行JIT分析或編譯。
然而,AOT編譯代碼還有一個更大的優點,那就是避免了「JavaScript橋樑」。當動態語言(如JavaScript)須要與平臺上的本地代碼互操做時,它們必須經過橋進行通訊,這會致使上下文切換,從而必須保存特別多的狀態(可能會存儲到輔助存儲)。這些上下文切換具備雙重打擊,由於它們不只會減慢速度,還會致使嚴重的卡頓。
說明:即便編譯後的代碼也可能須要一個接口來與平臺代碼進行交互,而且這也能夠稱爲橋,但它一般比動態語言所需的橋快幾個數量級。另外,因爲Dart容許將小部件等內容移至應用程序中,所以減小了橋接的需求。
Dart的另外一個好處是,Flutter不會從程序中拆分出額外的模板或佈局語言,如JSX或XML,也不須要單獨的可視佈局工具。如下是一個簡單的Flutter視圖,用Dart編寫:
new Center(child:
new Column(children: [
new Text('Hello, World!'),
new Icon(Icons.star, color: Colors.green),
])
)
複製代碼
而且隨着Dart 2的發佈,上面的代碼也變得愈來愈可讀,由於new和const關鍵字變得可選,因此靜態佈局看起來像是用聲明式佈局語言編寫的:
Center(child:
Column(children: [
Text('Hello, World!'),
Icon(Icons.star, color: Colors.green),
])
)
複製代碼
至於,困擾原生開發人員的一個問題是:爲何缺少專門的佈局語言怎麼會被稱爲優點呢?原生開發人員能夠在下面的文章中找到答案:「爲何原生應用程序開發人員應認真看待Flutter」
學習任何一門技術,最主要的渠道就是官方資料,因爲是Google的產品,所以從一開始就受到不少開發者的喜好,所以其社區建設也相對較快,讀者能夠現場Flutter中文社區瞭解一些Flutter開發的基礎,而後再結合一些開源項目進行學習。
Fluuter網上的學習資料也不少,能夠參考下面的連接進行深刻的學習:Flutter學習線路
參考: