Flutter為什麼使用Dart?

老孟Flutter發表於2020-05-11

老孟導讀:關於Flutter為什麼使用Dart?這個話題,就像PHP是世界上最好的語言一樣,爭論從來沒有停止過,有很多說法,比如:

  • Google是為了推廣Dart,Dart是親兒子。
  • Flutter團隊和Dart團隊相鄰,溝通起來更方便。

或許存在這樣的考慮,但即使是親兒子,爛泥也要能扶上牆才行啊,難道你真的覺得如此重大的決定是靠這些主觀色彩決定的?不可能的,所以Dart一定是有其非常大的優勢。

前言

在Flutter成立之初,Flutter團隊評估了10多種語言,Flutter團隊從四個主要維度進行評估,並考慮了框架作者,開發人員和終端使用者的需求。最終Dart在所有評估維度上得分都很高,並且符合所有要求和標準。

Dart在以下主要標準上贏得了高分:

  • 開發人員的生產力。Flutter的主要價值主張之一是,它可以讓開發人員使用相同的程式碼庫為iOS和Android建立應用程式,從而節省了工程資源。使用高效的語言可以進一步加速開發人員,並使Flutter更具吸引力。這對我們的框架團隊和開發人員都非常重要。Flutter的大多數語言都是用與我們提供給使用者的語言相同的語言構建的,因此我們需要在不犧牲開發人員的框架和小部件的可訪問性或可讀性的情況下,保持100k的程式碼行的生產力。
  • 物件導向。對於Flutter,我們需要一種適合Flutter問題領域的語言:建立視覺使用者體驗。該行業擁有數十年使用面嚮物件語言構建使用者介面框架的經驗。儘管我們可以使用非物件導向的語言,但這將意味著重新發明輪子來解決一些難題。另外,絕大多數開發人員都有物件導向開發的經驗,這使得學習Flutter開發方法變得更加容易。
  • 可預測的高效能。藉助Flutter,我們希望使開發人員能夠建立快速,流暢的使用者體驗。為了實現這一點,我們需要能夠在每個動畫幀中執行大量的最終開發人員程式碼。這意味著我們需要一種既能提供高效能又能提供可預測的效能的語言,而又不會導致幀丟失的定期暫停。
  • 快速分配。Flutter框架使用一種功能樣式的流程,該流程在很大程度上依賴於基礎記憶體分配器,可以有效地處理短暫的短期分配。此樣式是使用具有此屬性的語言開發的,在缺少此功能的語言中無法有效工作。

Dart

以下是Dart功能的列表,這些功能對於Flutter來說是必不可少:

  • Dart是AOT(Ahead Of Time)編譯的,編譯成快速,可預測的本機程式碼,幾乎所有Flutter都可以用Dart編寫。這不僅使Flutter更快,而且幾乎所有內容(包括所有小部件)都可以自定義。
  • Dart還可以通過JIT(Just In Time)進行編譯,以實現異常快速的開發週期和改變遊戲規則的工作流(包括Flutter亞秒級有狀態熱重灌)。
  • Dart使建立以60fps執行的平滑動畫和過渡更加容易。Dart可以在沒有鎖的情況下進行物件分配和垃圾回收。與JavaScript一樣,Dart避免了搶先式排程和共享記憶體(從而避免了鎖定)。因為Flutter應用程式已編譯為本機程式碼,所以它們不需要在領域之間建立緩慢的橋樑(例如,JavaScript與本機之間)。它們的啟動速度也快得多。
  • Dart允許Flutter避免使用像JSX或XML這樣的宣告式佈局語言,也不需要單獨的視覺化介面構建器,因為Dart的宣告式程式化佈局易於閱讀和視覺化。而且,由於所有佈局都以一種語言和一種位置顯示,因此Flutter可以輕鬆地提供使佈局變得輕鬆的高階工具。
  • 開發人員發現Dart特別易於學習,因為它具有靜態和動態語言使用者都熟悉的功能。

並非所有這些功能都是Dart獨有的,但是它們的結合達到了一個甜蜜點,這使得Dart在實施Flutter方面具有獨特的功能。如此之多,很難想象Flutter會像沒有Dart一樣強大。

編譯與執行

如果您已經瞭解靜態和動態語言,AOT和JIT編譯以及虛擬機器等主題,則可以跳過本節。

從歷史上看,計算機語言已分為兩類:靜態語言(例如,Fortran或C,其中在編譯時靜態鍵入變數)和動態語言(例如,Smalltalk或JavaScript,其中,變數的型別可以在執行時更改)時間)。通常會編譯靜態語言,以生成目標計算機的本機程式碼(或彙編程式碼)程式,這些程式在執行時由硬體直接執行。動態語言由直譯器執行,而不會產生機器語言程式碼。

當然,後來事情變得更加複雜。虛擬機器(VM)的概念變得很流行,它實際上只是一種模仿軟體中的硬體機器的高階直譯器。虛擬機器可以更輕鬆地將語言移植到新的硬體平臺。在這種情況下,VM的輸入語言通常是中間語言。例如,一種程式語言(例如Java)被編譯成一種中間語言(位元組碼),然後在VM(JVM)上執行。

另外,現在有即時(JIT)編譯器。JIT編譯器會在程式執行期間執行,並進行即時編譯。在程式建立期間(執行時之前)執行的原始編譯器現在稱為提前(AOT)編譯器。

通常,只有靜態語言才適合將AOT編譯為本機機器程式碼,因為機器語言通常需要知道資料的型別,而在動態語言中,型別不是預先固定的。因此,通常會解釋動態語言或編譯JIT。

在開發過程中 AOT 編譯,開發週期(從更改程式到能夠執行程式以檢視更改結果的時間)總是很慢。但是 AOT 編譯產生的程式可以更可預測地執行,並且執行時不需要停下來分析和編譯。AOT 編譯的程式也更快地開始執行(因為它們已經被編譯)。

相反,JIT編譯可提供更快的開發週期,但會導致執行速度較慢或更加不穩定。特別是,JIT編譯器的啟動時間較慢,因為在程式開始執行時,JIT編譯器必須在執行程式碼之前進行分析和編譯。研究表明,如果開始執行需要花費幾秒鐘的時間,那麼很多人就會放棄該應用程式。

以上就是 AOT 和 JIT 相關知識,將 AOT 和 JIT 編譯的優點結合起來不是很棒嗎?而Dart就是通過支援AOT 和 JIT 兩種型別的編譯而帶來顯著的優勢。

編譯並執行Dart

在研究Dart之前,Dart團隊的成員已經在高階編譯器和虛擬機器上進行了開創性的工作,既針對動態語言(如JavaScript 的V8引擎,針對Smalltalk的Strongtalk)又針對靜態語言(如Java 的Hotspot編譯器)。他們利用這種經驗使Dart在如何進行編譯和執行方面異常靈活。

Dart是極少數適合於同時編譯AOT和JIT的語言之一。支援這兩種編譯為Dart和(尤其是Flutter)提供了明顯的優勢。

在開發過程中使用JIT編譯,使用的編譯器特別快。然後,當應用程式準備釋出時,將對其進行AOT編譯。因此,藉助先進的工具和編譯器的幫助下,提供兩全其美的方案:極快的開發週期,並快速執行和啟動時間。

Dart在編譯和執行方面的靈活性不止於此。例如,Dart可以編譯為JavaScript以便瀏覽器可以執行。這允許在移動應用程式和Web應用程式之間重複使用程式碼。開發人員報告說,他們的移動和Web應用程式之間的程式碼複用率高達70%。通過將Dart編譯成本機程式碼,或編譯成JavaScript並將其與node.js結合使用,也可以在伺服器上使用Dart 。

最後,Dart還提供了一個獨立的VM,該VM使用Dart語言本身作為其中間語言(本質上像直譯器一樣工作)。

Dart可以有效地編譯AOT或JIT,解釋或轉換為其他語言。Dart的編譯和執行不僅異常靈活,而且速度特別

有狀態熱過載

Flutter最受歡迎的功能之一是其極快的熱過載。在開發期間,Flutter使用JIT編譯器,該編譯器通常可以在一秒鐘內重新載入並繼續執行程式碼。只要有可能,應用狀態就會在每次重新載入時保持不變,因此該應用可以從中斷處繼續執行。

除非您親自體驗過,否則很難理解真正快速(可靠)的熱過載在開發過程中有多重要。Flutter的熱載入功能使嘗試新想法或嘗試替代方法變得容易得多,極大地促進了創造力。

以下是一位移動應用程式開發人員對Flutter 熱過載的評價:

我想測試熱過載,所以我改變了顏色,儲存修改,結果……就喜歡上它了❤!

這個功能真的很棒。我曾認為 Visual Studio 中編輯和繼續(Edit & Continue)很好用,但這簡直令人驚歎。有了這個功能,我認為移動開發者的生產力可以提高兩倍。

這對我來說真的是翻天覆地的變化。當我部署程式碼並花費很長時間時,我分心了,做了其他事情,當我回到模擬器 / 裝置時,我就忘了想測試的內容。有什麼比花 5 分鐘將控制元件移動 2px 更令人沮喪?有了 Flutter,這不再存在。

避免卡頓

一個快速的應用程式是偉大的,但流暢的應用程式,甚至更好。即使是超級快的動畫,如果看起來很生澀,也會看起來很糟糕。但是,防止卡頓可能很困難,因為因素太多。Dart 有許多功能可以避免許多常見的導致卡頓的因素。

當然,(像任何語言一樣)仍然可以在Flutter中編寫一個簡陋的應用程式。Dart更具可預測性,可幫助開發人員更好地控制其應用的平滑度,從而更輕鬆地提供最佳的使用者體驗,無所不能。

Flutter建立的使用者介面以60 fps的速度執行,其效能遠優於其他跨平臺開發框架建立的使用者介面。

不僅比跨平臺應用程式更好,而且與最佳本機應用程式一樣好:

使用者介面非常流暢……我從未見過如此流暢的Android應用。

AOT彙編和“橋樑”

我們討論過一個有助於保持順暢的特性,那就是 Dart 能 AOT 編譯為本地機器碼。預編譯的 AOT 程式碼比 JIT 更具可預測性,因為在執行時不需要暫停執行 JIT 分析或編譯。

但是,AOT編譯程式碼有一個更大的優勢,那就是避免了“ JavaScript橋樑”。當動態語言(例如JavaScript)需要與平臺上的本機程式碼進行互操作時,它們必須通過網橋進行通訊,這會導致上下文切換必須儲存大量的狀態(可能儲存到輔助儲存)。這些上下文切換是雙重打擊,因為它們不僅使速度變慢,而且可能導致嚴重的問題。

注意:即使編譯的程式碼也可能需要與平臺程式碼進行對話的介面,這也可以稱為橋接,但是通常比動態語言所需的橋接要快幾個數量級。此外,由於Dart允許將小部件之類的內容移入應用程式,因此減少了跨過橋樑的需要。

搶先式排程,時間分片和共享資源

大多數支援多個併發執行執行緒的計算機語言(包括Java,Kotlin,Objective-C和Swift)都使用搶佔執行緒之間進行切換。每個執行緒都分配了一個“執行時間”,如果超過了分配的時間,則使用上下文切換來搶佔該執行緒。但是,如果在更新執行緒(例如記憶體)之間共享的資源時發生了搶佔,則這會導致爭用條件。

競爭狀況是雙重打擊,因為它們可能導致嚴重的錯誤,包括使應用程式崩潰並導致資料丟失,而且由於依賴於獨立執行緒的相對時間,因此特別難以查詢和修復它們。在偵錯程式中執行應用程式時,競爭條件會停止表現出來,這很常見。

解決爭用條件的典型方法是使用防止其他執行緒執行的鎖來保護共享資源,但是鎖本身可能會導致棘手甚至更嚴重的問題(包括死鎖飢餓)。

Dart 採取了不同的方法來解決這個問題。Dart 中的執行緒稱為 isolate,不共享記憶體,從而避免了大多數鎖。isolate 通過在通道上傳遞訊息來通訊,這與 Erlang 中的 actor 或 JavaScript 中的 Web Worker 相似。

Dart和JavaScript一樣,都是單執行緒的,這意味著它根本不允許搶佔。相反,執行緒顯式地產生(使用async / await,FuturesStreams)。這使開發人員可以更好地控制執行。單執行緒可幫助開發人員確保關鍵功能(包括動畫和過渡)在沒有搶佔的情況下得以執行。這不僅對使用者介面,而且對於其他客戶端-伺服器程式碼,通常都是一個很大的優勢。

當然,如果開發人員忘記放棄控制,這可能會延遲其他程式碼的執行。但是,我們發現,忘記屈服通常比忘記鎖定容易得多(因為很難找到競爭條件)。

物件分配和垃圾回收

造成垃圾的另一個嚴重原因是垃圾收集。確實,這只是訪問共享資源(記憶體)的一種特殊情況,在許多語言中,這都需要使用鎖。但是在收集可用記憶體時,鎖可能會阻止整個應用程式執行。但是,Dart幾乎可以在沒有鎖的情況下幾乎始終執行垃圾回收。

Dart 使用先進的分代垃圾回收和物件分配方案,該方案對於分配許多短期物件(對於Flutter 這樣的反應式使用者介面來說非常完美,Flutter 為每幀重建不可變檢視樹)而言非常快。Dart 可以用一個指標凹凸分配一個物件(無需鎖定)。這將導致平滑的滾動和動畫效果,而不會產生現卡頓。

統一佈局

Dart的另一個好處是Flutter不會在您的程式和其他模板化或佈局語言(例如JSX或XML)之間拆分佈局,也不需要單獨的視覺化佈局工具。這是用Dart編寫的簡單Flutter檢視:

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

但是,我知道您可能在想什麼- 缺少專門的佈局語言如何被稱為優勢?但它確實是顛覆性的。這是開發人員在題為“ 為什麼本機應用程式開發人員應認真看待Flutter ” 的文章中寫的。

在 Flutter 裡,介面佈局直接通過 Dart 編碼來定義,不需要使用 XML 或模板語言,也不需要使用視覺化設計器之類的工具。

我的預感是,聽到這個訊息後,你們中的一些人甚至會畏縮一點。表面看來,這也是我的反應。使用視覺工具進行佈局難道不是一件容易的事。用程式碼編寫各種約束邏輯會不會使事情變得過於複雜?

結果不然。天啊,它簡直讓我大開眼界。

答案的第一部分是上面提到的熱過載。

這比 Android 的 Instant Run 和任何類似解決方案不知道要領先多少年。對於大型的應用同樣適用。如此快的速度,正是 Dart 的優勢所在。

實際上,視覺化編輯器就變得多餘了。我一點都不懷戀 XCode 的自動重佈局。

Dart 建立的佈局簡潔且易於理解,而“超快”的熱過載可立即看到結果。這包括佈局的非靜態部分。

結果,在 Flutter 中進行佈局要比在 Android/XCode 中快得多。一旦你掌握了它(我花了幾個星期),由於很少發生上下文切換,因此會節省大量的開銷。不必切換到設計模式,選擇滑鼠並開始點選,然後想是否有些東西必須通過程式設計來完成,如何實現等等。因為一切都是程式化的。而且這些 API 設計得非常好。它很直觀,並且比自動佈局 XML 更強大。

例如,下面是一個簡單的列表佈局,該列表佈局以程式設計方式定義的所有其他專案之間新增了分隔線(水平線):

return new ListView.builder(itemBuilder: (context, i) {
  if (i.isOdd) return new Divider(); 
  // rest of function
});複製程式碼

在 Flutter 中,無論是靜態佈局還是程式設計佈局,所有佈局都存在於同一個位置。新的Dart 工具,包括Flutter Inspector 和大綱檢視(利用所有的佈局定義都在程式碼裡)使複雜而美觀的佈局更加容易。

Dart是專有語言嗎?

不,Dart(如 Flutter)是完全開源的,具備清楚的許可證,同時也是 ECMA 標準的。Dart 在 Google 內外很受歡迎。在谷歌內部,它是增長最快的語言之一,並被 Adwords、Flutter、 Fuchsia 和其他產品使用;在谷歌外部,Dart 程式碼庫有超過 100 個外部提交者。

Dart開放性的更好指標是Google以外社群的發展。例如,我們看到來自第三方的Dart文章和視訊源源不斷(包括Flutter和AngularDart),我在本文中引用了其中的一些。

除了Dart本身的外部提交者之外,公共Dart軟體包儲存庫中還有3000多個軟體包,包括Firebase,Redux,RxDart,國際化,加密,資料庫,路由,集合等的庫。

Dart程式設計師會容易找到嗎?

如果沒有很多程式設計師知道Dart,找到合格的程式設計師會更困難嗎?當然不是,Dart使它更容易找到程式設計師,因為它是一種非常快速且易於學習的語言。Java,JavaScript,Kotlin,C#或Swift等語言的程式設計師幾乎可以立即在Dart中開始程式設計。最重要的是,熱過載鼓勵使用者玩Dart並嘗試新事物,這使得學習Dart更快,更愉快。

這是一個程式設計師在題為“ 為什麼Flutter將在2018年騰飛 ”的文章中所說的:

Dart是用於開發Flutter應用程式的語言,學習起來很容易。Google擁有建立簡單,記錄良好的語言(例如Go)的經驗。到目前為止,對我而言,Dart使我想起了Ruby,這是一種學習的樂趣。它不僅適用於移動裝置,也適用於Web 開發

另一篇關於Flutter和Dart的文章,標題為“ 為什麼要Flutter?而不是框架X?甚至更好,為什麼我要全力以赴。

Flutter使用由Google建立的Dart語言,說實話,我不喜歡C#或JAVA之類的強型別語言,但我不知道Dart編寫程式碼的方式為什麼看起來有所不同。我寫起來很舒服。也許是因為它非常簡單易學。

通過廣泛的UX研究和測試,Dart專門設計為熟悉且易於學習。例如,在2017年上半年,Flutter團隊與八名開發人員進行了UX研究。我們向他們簡要介紹了Flutter,然後將它們鬆散了一個小時左右,以建立一個簡單的檢視。所有參與者都能夠立即開始程式設計,即使他們以前從未使用過Dart。他們專注於編寫響應式檢視,而不是語言。Dart 直接就能上手用了。

最後,一位參與者(在任務中取得了特別大的進步)沒有提及該語言,因此我們詢問他們是否意識到自己使用的是哪種語言。他們不知道。語言沒關係 ; 他們在幾分鐘內就可以在Dart中程式設計。

學習新系統的難點通常不是學習語言,而是學習所有編寫好的程式碼的庫,框架,工具,模式和最佳實踐。而且Dart庫和工具都非常出色,並且文件齊全。一篇文章宣稱:“作為獎勵,他們還非常注意自己的程式碼庫,並且擁有我見過的最好的文件。” 學習Dart只需花很少的精力就可以通過節省學習其餘時間的時間來彌補。

作為直接的證據,Google內部的一個大型專案希望將其移動應用程式移植到iOS。他們打算僱用一些iOS程式設計師,但決定嘗試Flutter。他們監控了使開發人員快速掌握Flutter所花費的時間。他們的結果表明,程式設計師可以在三週內學習Dart Flutter並提高工作效率。相比之下,他們之前觀察到的五個星期可以使程式設計師僅在Android上就可以上手(更不用說他們必須僱用和培訓iOS的開發人員)。

最後,文章“ 我們為什麼選擇Flutter以及它如何使我們的公司變得更好 ”來自一家將大型企業應用程式遷移到所有三個平臺(iOS,Android和Web)上的Dart的公司。他們的結論:

招人變得容易多了。無論他們是來自 Web、iOS 還是 Android,我們現在都希望接受最佳人選。

現在我們擁有 3 倍的工作效率,因為我們所有的團隊都集中在一個程式碼庫上。

知識共享達到前所未有的高度。

通過使用Dart和Flutter,他們能夠將生產力提高三倍。鑑於他們之前所做的事情,這不足為奇。與許多公司一樣,他們正在使用獨立的語言,工具和程式設計師為每個平臺(Web,iOS和Android)構建獨立的應用程式。改用Dart意味著他們不再需要僱用三種不同的程式設計師。對於他們來說,將現有的程式設計師轉移到Dart上很容易。

他們和其他人發現,一旦程式設計師開始使用Flutter,他們通常會愛上Dart。他們喜歡語言的簡潔性和缺乏儀式感。他們喜歡語言功能,例如級聯,命名引數,非同步/等待和流。最重要的是,他們喜歡Dart所提供的Flutter功能(例如熱過載),而Dart幫助他們構建的漂亮,高效能的應用程式。

祕訣就是專注

Dart 2中的改進集中在優化客戶端開發上。但是Dart仍然是構建伺服器端,桌上型電腦,嵌入式系統或其他程式的絕佳語言。

專注是一件好事。專注於幾乎可以使所有持久的流行語言受益。例如:

  • C是用於編寫作業系統和編譯器的系統程式語言。它變得更多了。
  • Java是為嵌入式系統設計的語言。
  • JavaScript是Web瀏覽器的指令碼語言(!)。
  • 甚至備受反對的PHP也成功了,因為它專注於編寫“個人主頁”(並以此為名)。

另一方面,許多語言已經明確嘗試(但失敗)成為完全通用的語言,例如PL / 1和Ada等。最常見的問題是,沒有集中注意力,這些語言就成了眾所周知的廚房水槽。

使Dart成為出色的客戶端語言的許多功能也使它成為伺服器端使用的更好語言。例如,Dart避免了搶先式多工這一事實使它具有與伺服器上的Node相同的優勢,但打字效果更好,更安全。

為嵌入式系統編寫軟體也是如此。Dart可靠地處理多個併發輸入的能力是關鍵。

最後,Dart在客戶端上的成功將不可避免地引起更多在伺服器上使用它的興趣-就像JavaScript和Node發生的情況一樣。為什麼要強迫人們使用兩種不同的語言來構建客戶端伺服器軟體?

結論

這對於 Dart 來說是一個激動人心的時刻。使用 Dart 的人喜歡它,而 Dart 2 中的新特性使其成為你工具庫中更有價值的補充。如果您沒有使用Dart,希望本文為您提供有關Dart的新功能或不同之處的有價值的資訊,並且您可以嘗試使用它和Flutter。

檢視英文原文: https://hackernoon.com/why-flutter-uses-dart-dd635a054ebf

交流

老孟Flutter部落格地址(近200個控制元件用法):laomengit.com

歡迎加入Flutter交流群(微信:laomengit)、關注公眾號【老孟Flutter】:

相關文章