學了將近3天的Flutter,準備棄坑了...

咱實話實說,Flutter真有這麼香嗎?看語言指數蹭蹭的漲,居然有人預測會超過RN,將來一統天下?

就這層層嵌套嵌套~寫個UI就像繞迷宮,年齡大了,眼神不好真幹不了這個。

一個好框架一開始就會讓人不知不覺喜歡,記得當年第一次接觸到Vue,一晚上就做了個demo,直接上手。

Dart是個好語言,但google能不能最起碼把布局分開啊?算了~洗洗睡了,打算以後就老老實實RN+Electron擼了。玩不起。

大家有何高見?就這嵌套+樣式布局不分離這一點。個人非常不看好Flutter

(大多數跨平台框架)上圖這樣的渲染過程,

貌似讓接近原生般的跨平台應用構建變得簡單,不過細節決定成敗,由於依賴目標平台的組件進行渲染,這樣就需要通過目標平台widget和框架widget數據同步的屬性映射層,導致將每個動畫映射到特定於平台的widget調用。

相比之下,Flutter不需要任何針對平台的UI組件去渲染其UI,它為了渲染應用用戶界面的唯一前提就是canvas,類下圖:

Flutter的渲染方式使其鶴立雞群,消除了開發者對不同平台上UI一致性的任何擔憂。

2.減少開發時間

根據我們的經驗,構建一個普通的中型代碼量Android應用也至少需要40秒才能交付到測試設備上;有時,調整布局中的較小外觀可能需要花費很多時間。

有人可能會說:Android Studio為此提供了布局預覽。但是,有一個缺點:該功能是有限的,並非總是能按預期運行,尤其是在使用自定義視圖時。

Flutter的「熱載入」功能又使你幾乎可以立即看到已應用的更改,甚至不會丟失當前的應用狀態。這正是利用flutter開發應用能夠大大提速的原因。

Flutter團隊投入大量精力為開發者提供各種現成的widget,很多widget甚至是可自定義的,這點與以往其他框架一樣,又節省了你的時間;除了眾多的核心布局widget之外,Flutter還提供了大量的Material和Cupertino小部件,可以完美的模仿每種設計語言的行為,大概工作原理如下:

歸納起來,使用Flutter,你會跳過應用開發中的幾個超耗時的步驟。

3. 加快產品上線速度

在大多數情況下,與單獨為Android和iOS開發的同一個應用相比較,Flutter應用所需的開發工時至少要少兩倍。

原因簡單:你不必單獨為特定的平台去編寫代碼,就可以獲得所需的視覺效果;任何基於2D的UI都可以在Flutter中實現,同時無需與本機應用扯上關係。

除此之外,Flutter還提供了用於構建UI的聲明式API,可以顯著提高性能,特別是涉及視覺調整相關的工作時,這個優勢尤其突出。

4. 媲美原生

Flutter直接對接到了底層的繪製引擎,而不像RN得需要先轉化成原生系統提供的UI組件,所以理論上來說Flutter在性能方面應該是等同於原生的,但是由於系統通常會對原生應用有著諸多的優化,所以也只能含蓄的用「媲美」一詞。那麼Flutter這樣的設計也使得Flutter在多端一致性方面碾壓其它跨平台方案。

5. 實現任何複雜、自定義動畫UI

Flutter的最大優點之一是可以自定義屏幕上顯示的任何內容,而不論它多麼複雜。

儘管原生也可以實現自定義的UI,但對比起來所需的工作量投入是不同的。

下面是一個簡單但自定義的UI的示例:

可以說,Flutter使該過程更加靈活和通用,也不會增加工作量。共享元素過渡,形狀/顏色/陰影、剪切、過度, 這些都可以輕鬆實現。

6.獨立渲染引擎

前面所說的,如果沒有高性能的跨平台渲染引擎,上述功能大部分將無法實現。

Flutter使用Skia來渲染到平台提供的canvas上,由於有了高性能引擎,Flutter內置的UI幾乎可以在任何平台上啟動。換句話說,不再需要調整UI即可將其遷移到目標平台上,極大地簡化了開發過程。

7. 針對平台的簡單邏輯實現

除了UI外,許多當下移動應用非常依賴高級OS級別的功能,例如:獲取GPS坐標、藍牙通信、收集感測器數據、許可權處理等,而其中許多功能在開發Flutter應用時是可以通過Google提供的即用型插件去打通的。

當然,在某些情況下總會有無法提供的插件,Flutter也考慮到了,它的解決方案是,通過平台渠道在平台本機代碼和Dart之間建立通信,這樣的話,僅在原生方面付出一點額外的努力,你就可以在Flutter應用上實現原生應用可以執行的任何操作。

示例如下:

8. 已不僅僅是移動端

最後,你不僅可以在移動設備上進行Flutter應用開發,而且也有Flutter for Web和Flutter Desktop Embeddings。例如,在2020年的I/O會議上,Google展示了Flutter Web的技術前瞻,這使在瀏覽器中運行純Flutter應用變成了可能,注意,這是無需修改源碼的。


總結,Flutter和Dart語言的合璧,加之谷歌正在精心打造的Fuchsia操作系統,或許谷歌的野心是有一天讓通過Flutter框架開發的應用運行在不同的智能設備上。

那麼,恐怕不僅僅是「有人喜歡Flutter」,而是會有更多開發者加入利用這套框架進行應用開發的行列中。

編輯於 2020-12-30繼續瀏覽內容知乎發現更大的世界打開Chrome繼續閑魚技術閑魚技術?

已認證的官方帳號

長文預警,帶大家重新認識一下Flutter。

Flutter也許不再是非常熱門時髦的話題了,但作為一項已經逐漸進入規模化實踐的技術,它的價值已經初步獲得認可,後續應該有不錯的生命力。作為較早期的Flutter實踐者,我一直在思考Flutter的技術價值以及如何釋放這些價值,本篇嘗試從一個新的視角去結構化的梳理Flutter的技術價值並做對應的應用分析。這裡不會涉及到Flutter具體領域的技術點,但是會結合我們團隊過去的探索實踐,在技術使用策略的層面做一些總結,希望能幫助到小夥伴們在開發實踐中思考提煉,抬頭看路,仰望星空,找到未來的創新方向。

一. 前端有些啥問題

要溯源Flutter, 就得從前端說起了。這裡的前端是相對於後端的概念,大概泛指通過圖形界面實現用戶交互的終端技術。這個領域一直很有活力,伴隨著互聯網一路走來,很多新思路和新技術都有點眼花繚亂:上古的MVC已經不大提起了,老一輩的MVP,MVVM也逐漸暗淡,新一輩的Vue,Angular,React方興未艾,還有Redux, Mobx, Hooks推波助瀾。這些技術都像是一個個有感情的小生命,有的熱情,有的文藝,有的高冷,十分熱鬧。也許你會想:它們都在說個啥?它們都想解決一個啥問題?

1. 節點,連接和網路

互聯網是這一切存在的大背景,互聯網有3個大要素:節點,連接和網路拓撲結構。每一個要素的進化都會給前端帶來升級和變革:從PC互聯網到移動互聯網再到物聯網是節點在進化;充滿想像的5G時代是連接在進化;從中心化到分散式是網路拓撲結構在進化。前端的使命是讓用戶(人)高效的嵌入到網路之中,讓人和設備融合為一個有生命的網路「節點」。

PS:網路模型可以適配到前端的很多場景,裡面的「節點」可以代指手機設備,應用程序,進程,頁面,甚至組件。

2. 節點與前端技術

前端技術是用戶(人)與設備的粘合劑,讓二者有機的構成一個網路節點。我嘗試剖析下前端技術在節點中的形態:首先它需要提供界面給用戶,並響應用戶的交互;需要管理和遠端節點的通信,交換信息;還需要管理當前節點的信息狀態;最後,為了方便的嵌入到網路中,節點需要一個友好的「外觀」,就是生命周期。生命周期描述了節點的誕生,消亡,所擁有的權益,和所承擔的責任。

PS:這個分治模型也具有一定的通用性,可以適用在應用程序,頁面,或者組件。

3. 前端要解決的問題

當然,前端技術作為一種軟體技術,在日常的工程開發中也需要基礎的構建部署支撐。那麼,綜合前面的討論,前端要解決的基礎要素問題有:

  • 遠端通信
  • 界面管理
  • 生命周期
  • 狀態管理
  • 構建部署

這裡面生命周期管理是一個比較「隱形」的問題,它其實就是構建「外觀」描述,也就是「組件化」。這些基礎要素問題的結構關係大概是:

這幾個基礎要素問題的解決往往不能孤立的進行,在設計解決方案的時候需要彼此配合。前端領域的技術方案通常都會合併解決其中的幾個問題,比如:React解決界面管理和生命周期;Vue解決了界面管理,狀態管理,和生命周期;Redux專註解決狀態管理;GraphQL,BFF,Serverless解決遠端通信;webpack解決構建部等等...

那麼,Flutter解決了什麼問題?或者,Flutter可以解決哪些問題呢?

二. Flutter都有些啥

有趣的技術方案應該有自己旗幟鮮明的個性,做架構設計往往是遇到了獨特的問題或者發現了更好的工具。因此,使用Flutter做解決方案的時候,應該梳理下Flutter都帶來了些什麼。一般來說,主要有Dart語言,Dart運行時(VM),GUI框架,和相關的開發構建工具。

1. Dart語言

Dart語言不好說有多優秀,總的來說是一門工程「友好」的現代語言。也許感覺平淡無奇,但官方在介紹Flutter的時候,還略有「驕傲」的展示了它的包容性:它能較為原生的支持聲明式,過程式,面向對象,函數式,和響應式等業務場景,它給技術方案實現提供了很自由的範式空間,這是值得發掘和嘗試的。結合我自己的實踐,有幾個點值得一說:

  • 支持類似「協程」處理(async/await/yield):Dart是單線程的,但是支持非同步。這一點需要在使用中去體會,不展開說,理解深了以後,可能對很多問題都有新解法。
  • 提供Stream:當你要進階學習Flutter的時候,很多地方能見到它。它能做流式數據處理,函數組合,傳輸控制,屬於進階必知必會。
  • mixin特性:這是很有用的特性,尤其在架構設計方面。它提供了新的組合方式,在做功能組合的時候,Dart可以使用對象注入,或者高階函數,或者mixin。

2. Dart-Runtime / VM

當你引入Flutter,你就有一個Dart-Runtime啦。當然,它本來的意義是支持Flutter運行的,然而就像JS的V8引擎一樣,本來是用來支持H5頁面的,後面的腦洞就越開越大了。當然Dart沒有JS的動態能力(特殊的場合也可以),但它是跨端的,而且aot性能有保障,發掘空間較大,還能同時覆蓋幾乎所有場景,手機app開發,PC的構建部署,服務端,甚至serverless運行時。

3. Flutter應用開發框架

Flutter帶來了高性能的跨平台GUI Framework,這沒啥可說的,用就是了!但如果已經有了自己的開發生態,捨棄成本太大,又想「借用」下Flutter的技術優勢,大概有幾種方案:

  • 語言轉換,基本上就是把其他語言的布局結果交給Flutter Framework。
  • 中層Framework介入,選擇一棵樹介入,這樣對接面會小一些。
  • 底層Framework替換,整個替換掉Flutter Framework, 直接使用底層的Engine。

當然,還有一種方式就是混合開發了,需要實現混合棧管理,而且在1.22版本以後,Flutter升級了Navigator組件,提供了Navigator 2.0,這對混合開發是一個利好。

4. 開發構建工具

值得一提的是HotReload,誰用誰知道。熱部署不僅界面開發需要,這是個通用需求,如果在服務端通過Dart實現一個,也是極好的。

Flutter的構建工具並無太多亮點,而且因為Dart語言在Flutter中不支持反射(產物太大,增加包體積),業務架構實現上很多需要依賴於編譯時處理的技術,這對構建系統的能力有較大依賴的。換一個角度,因為這一領域尚沒有成熟方案,加上Dart的工程「友好」,可能實現由一種語言來統一前端開發,後端開發,以及構建和部署,真做到了會很酷!

三. Flutter可以有些啥玩法

討論前端要解決的幾個基礎要素問題,也討論了Flutter帶來的技術工具,結合這兩點,看看利用Flutter都能做些啥。

1. 遠端通信

「遠端通信」是一個做了抽象的概念,具體形式會根據「節點」的定義不同而不同。可以是指物理設備之間的通信(手機與伺服器),也可以指模塊之間(頁面與另一個頁面)的通信,還可以指組件之間(兩個StatefulWidget之間)的通信。因為在Flutter中「一切皆是Widget」,所以簡化的看,Flutter裡面大概分為兩種情形:面向伺服器的通信和組件(Widget)之間的通信。

  • 面向伺服器的通信:這方面有傳統的Restful,GraphQL,還有興起於「雲原生」概念的Serverless。藉助於Dart的能力延伸,Dart-Runtime可以成為Serverless的可選容器,那麼前後兩端都可以使用Dart來開發,如果再用Dart補足中間的構建部署pipeline,那麼可以搭建出一個很「雲原生」概念的應用程序開發流(dev flow):

Flutter的跨端能力結合雲原生的彈性部署,前後端的實現可以放到一起,它們之間的調用也變得簡單自然,有理由相信這會是一個高效的開發方式。閑魚已經做了前期的探索,並在業務中嘗試落地。

此外,GraphQL與Flutter也是值得嘗試的組合,GraphQL和React範式在理念上很對味口,但是我們並沒有嘗試過。

  • 組件之間的通信:Flutter提供的基礎業務編程組件是StatefulWidget和StatelessWidget,它們是按樹形結構來組織的,並提供了InheritedWidget來支持它們之間的通信,在通信方式可以總結出3種:
    1. Notify型:通知/監聽模式,Flutter提供了ValueNotifier和ChangeNotifier, 簡單方便,適用於輕量信息通信,參見Provider。
      1. Transmission型:數據傳輸模式,Dart提供了Stream來支持這種模式。使用靈活,擴展方便,幾乎是框架設計必備,參見BLoC。
        1. Invoke型: 介面調用模式,類似輕量RPC方式,在Flutter的應用架構設計中竟然很少見到。它確實有些重,但是有前面的模式沒有的優勢:它是雙向的。

        2. 狀態管理

        狀態管理是個大問題,它由兩個元素構成:狀態和處理狀態的邏輯。在代碼實現上,狀態就是數據,邏輯就是函數。當它們變得複雜的時候,解決的辦法其實就是拆分,然後再合理的組合。我嘗試從狀態和邏輯的拆分選擇上來列舉所有可能的解法:

        • 1. 狀態不拆,拆分邏輯: 這種做法的特點全局共用一個狀態結構體對象,所有狀態全部放在這個對象中,叫做「統一狀態管理」。只有一個數據對象,就消除了各個處理邏輯之間信息共享問題,邏輯內部沒有狀態,變得非常的純粹(比如純函數來實現),再將邏輯以合適的方式組合成一個整體,實現上界限清晰,簡單優雅,代表的方案就是Redux。 如果採用這種設計方案,推薦使用函數式風格來實現,這倒不是因為函數式「更高效」,「更優雅」之類的,而是它與函數式的思路十分的契合,在實現上更容易把握住思路。用面向對象來實現也並沒有問題,最後的效果取決於你所面臨的工程環境和用戶。 這種狀態管理好處顯而易見:一處狀態發生改變,不需要到處發事件同步。但是如果用在複雜大業務上面(比如一個有數十個頁面流程的業務產品),狀態必定是複雜的,狀態結構體必然是龐大的。Redux的方式很好的管理了邏輯,如果要管理一個統一龐大的狀態數據,也許內存級別的SQL是個不錯的主意,GraphQL-Client給了我們啟發,我們也正在嘗試實踐。

        • 2. 邏輯不拆,拆分狀態: 我把這種叫做「步進狀態管理」,實際上這類似於狀態機模式。但如果要真正使用,狀態必須是有限的,而且不能經常變動。這與互聯網持續多變的業務需求實際是不符合的,所以採用這種方式的設計幾乎沒有。但在一些很嚴肅的業務場景中,比如交易流程,一旦定下來就不容易變動。這時,步進狀態管理就很合適了。

        • 3. 同時拆分邏輯和狀態: 這是容易想到方案,在更細的粒度上,將狀態和它對應的處理邏輯拆分打包,變成更小的域(scope),然後統一協調這些子域(subModel),我把這種叫做「組合狀態管理」。進一步的方案可以統一定義subModel的基礎行為,然後引入調度器來協調管理它們,subModel之間還可以共享上下文來共享信息等等。 這種思路形式自由,可以採用的實現方式很多,經典的面向對象當然不在話下,scoped_model採用的就是這種思路,scoped_model實現的簡單易懂,同時能力也比較有限。當然也可以採用函數式的方式,高階函數+閉包也能很好的實現,但是圈內沒有看到有相關的設計實現。還有一點,Dart提供了Mixin特性,通過這個特性,可以得到更簡潔的實現方案。比如,可以沉澱很多特定的Model,然後通過with選擇組合到業務Model中來(參考Flutter Framework中WidgetsBinding的實現)。目前flutter-hook在做這方面的探索,flutter-hook看起來有些迷惑,其核心就是利用了Dart的Mixin特性來組合狀態。

        3. 界面管理

        Flutter使用了響應式UI,目的就是讓業務開發減少界面的管理工作,只要提供好頁面「描述」就行了。雖然Flutter內建了類似Virtual Dom的Diff機制,但是,做這個Diff也是要費性能的,如果我們在框架設計上能內建的把Diff工作提前到數據層,是不是可以提升性能呢?

        我們嘗試了幾種方法,受制於在Flutter中Dart不能反射,效果不理想,也許後續生態完善之後會有好的解法。

        在UI開發中,Flutter一直有一個隱隱的聲音就是動態化,官方好像是「忽略」的,這裡也不談了。

        4. 生命周期

        Flutter通過StatefulWidget給業務開發提供了基礎的生命周期管理。組件生命周期的設計是隨著業務場景的不同而不同的,我自己的理解,設計生命周期要從兩點出發:一是組件從誕生到消亡的時間線,二是組件在場景中所擁有的權益和所承擔的責任。生命周期的擴展原點是StatefulWidget,因業務場景不同而擴展不同,很難展開講。

        舉個例子,如果使用原生Flutter開發(或者叫純Flutter開發),StatefulWidget所提供的生命周期是足夠的。但是如果要做混合開發,引入混合棧後,顯然就不夠用了。這時候就需要提供新的組件來擴展生命周期,更好的滿足混合場景的開發。當時我在做混合棧的時候並沒有能理解到這一點。

        四. 結語

        本篇從分析前端開發需要面對的幾個基礎核心問題入手,結合Flutter帶來的技術工具,嘗試結構化的分析Flutter在業務開發中可能的技術選擇和探索方向。當然,技術同學既要仰望星空,還需要腳下看。

        對於Flutter開發中的熱點技術問題,歡迎關注閑魚技術公眾號的其他文章,或者加入我們,和閑魚一起做一點不一樣的技術!

        發佈於 01-22繼續瀏覽內容知乎發現更大的世界打開Chrome繼續暗落亭苦來暗落亭苦來這兒沒有什麼值得看的東西了

        我還真挺喜歡Flutter,也成功轉職了。

        我覺得我沒有成見,先從事Android,後來學React Native,再後來才學的Flutter。

        對比優劣,不多說,得罪人。但回答了題主的反問吧。

        代碼嵌套從一開始是不太習慣,現在已經接受。

        原因大概有幾點:

        1、一覽代碼並沒有多少意義。改代碼也好,改bug也好,不需要一覽幾百行代碼。寫好注釋,快速找到控制項位置,其實真的要讀要看的代碼,不會太多。至於截圖裡的代碼,一眼就能看出是什麼在幹什麼了。可能開始不習慣。

        2、代碼量在減少。我實際對比了下代碼量,Flutter遠遠小於Android原生。

        估計題主是web出身,所以對強大的css熟悉了。我作為原生開發,被xml折磨已久。


        長文預警,帶大家重新認識一下Flutter。

        Flutter也許不再是非常熱門時髦的話題了,但作為一項已經逐漸進入規模化實踐的技術,它的價值已經初步獲得認可,後續應該有不錯的生命力。作為較早期的Flutter實踐者,我一直在思考Flutter的技術價值以及如何釋放這些價值,本篇嘗試從一個新的視角去結構化的梳理Flutter的技術價值並做對應的應用分析。這裡不會涉及到Flutter具體領域的技術點,但是會結合我們團隊過去的探索實踐,在技術使用策略的層面做一些總結,希望能幫助到小夥伴們在開發實踐中思考提煉,抬頭看路,仰望星空,找到未來的創新方向。

        一. 前端有些啥問題

        要溯源Flutter, 就得從前端說起了。這裡的前端是相對於後端的概念,大概泛指通過圖形界面實現用戶交互的終端技術。這個領域一直很有活力,伴隨著互聯網一路走來,很多新思路和新技術都有點眼花繚亂:上古的MVC已經不大提起了,老一輩的MVP,MVVM也逐漸暗淡,新一輩的Vue,Angular,React方興未艾,還有Redux, Mobx, Hooks推波助瀾。這些技術都像是一個個有感情的小生命,有的熱情,有的文藝,有的高冷,十分熱鬧。也許你會想:它們都在說個啥?它們都想解決一個啥問題?

        1. 節點,連接和網路

        互聯網是這一切存在的大背景,互聯網有3個大要素:節點,連接和網路拓撲結構。每一個要素的進化都會給前端帶來升級和變革:從PC互聯網到移動互聯網再到物聯網是節點在進化;充滿想像的5G時代是連接在進化;從中心化到分散式是網路拓撲結構在進化。前端的使命是讓用戶(人)高效的嵌入到網路之中,讓人和設備融合為一個有生命的網路「節點」。

        PS:網路模型可以適配到前端的很多場景,裡面的「節點」可以代指手機設備,應用程序,進程,頁面,甚至組件。

        2. 節點與前端技術

        前端技術是用戶(人)與設備的粘合劑,讓二者有機的構成一個網路節點。我嘗試剖析下前端技術在節點中的形態:首先它需要提供界面給用戶,並響應用戶的交互;需要管理和遠端節點的通信,交換信息;還需要管理當前節點的信息狀態;最後,為了方便的嵌入到網路中,節點需要一個友好的「外觀」,就是生命周期。生命周期描述了節點的誕生,消亡,所擁有的權益,和所承擔的責任。

        PS:這個分治模型也具有一定的通用性,可以適用在應用程序,頁面,或者組件。

        3. 前端要解決的問題

        當然,前端技術作為一種軟體技術,在日常的工程開發中也需要基礎的構建部署支撐。那麼,綜合前面的討論,前端要解決的基礎要素問題有:

        • 遠端通信
        • 界面管理
        • 生命周期
        • 狀態管理
        • 構建部署

        這裡面生命周期管理是一個比較「隱形」的問題,它其實就是構建「外觀」描述,也就是「組件化」。這些基礎要素問題的結構關係大概是:

        這幾個基礎要素問題的解決往往不能孤立的進行,在設計解決方案的時候需要彼此配合。前端領域的技術方案通常都會合併解決其中的幾個問題,比如:React解決界面管理和生命周期;Vue解決了界面管理,狀態管理,和生命周期;Redux專註解決狀態管理;GraphQL,BFF,Serverless解決遠端通信;webpack解決構建部等等...

        那麼,Flutter解決了什麼問題?或者,Flutter可以解決哪些問題呢?

        二. Flutter都有些啥

        有趣的技術方案應該有自己旗幟鮮明的個性,做架構設計往往是遇到了獨特的問題或者發現了更好的工具。因此,使用Flutter做解決方案的時候,應該梳理下Flutter都帶來了些什麼。一般來說,主要有Dart語言,Dart運行時(VM),GUI框架,和相關的開發構建工具。

        1. Dart語言

        Dart語言不好說有多優秀,總的來說是一門工程「友好」的現代語言。也許感覺平淡無奇,但官方在介紹Flutter的時候,還略有「驕傲」的展示了它的包容性:它能較為原生的支持聲明式,過程式,面向對象,函數式,和響應式等業務場景,它給技術方案實現提供了很自由的範式空間,這是值得發掘和嘗試的。結合我自己的實踐,有幾個點值得一說:

        • 支持類似「協程」處理(async/await/yield):Dart是單線程的,但是支持非同步。這一點需要在使用中去體會,不展開說,理解深了以後,可能對很多問題都有新解法。
        • 提供Stream:當你要進階學習Flutter的時候,很多地方能見到它。它能做流式數據處理,函數組合,傳輸控制,屬於進階必知必會。
        • mixin特性:這是很有用的特性,尤其在架構設計方面。它提供了新的組合方式,在做功能組合的時候,Dart可以使用對象注入,或者高階函數,或者mixin。

        2. Dart-Runtime / VM

        當你引入Flutter,你就有一個Dart-Runtime啦。當然,它本來的意義是支持Flutter運行的,然而就像JS的V8引擎一樣,本來是用來支持H5頁面的,後面的腦洞就越開越大了。當然Dart沒有JS的動態能力(特殊的場合也可以),但它是跨端的,而且aot性能有保障,發掘空間較大,還能同時覆蓋幾乎所有場景,手機app開發,PC的構建部署,服務端,甚至serverless運行時。

        3. Flutter應用開發框架

        Flutter帶來了高性能的跨平台GUI Framework,這沒啥可說的,用就是了!但如果已經有了自己的開發生態,捨棄成本太大,又想「借用」下Flutter的技術優勢,大概有幾種方案:

        • 語言轉換,基本上就是把其他語言的布局結果交給Flutter Framework。
        • 中層Framework介入,選擇一棵樹介入,這樣對接面會小一些。
        • 底層Framework替換,整個替換掉Flutter Framework, 直接使用底層的Engine。

        當然,還有一種方式就是混合開發了,需要實現混合棧管理,而且在1.22版本以後,Flutter升級了Navigator組件,提供了Navigator 2.0,這對混合開發是一個利好。

        4. 開發構建工具

        值得一提的是HotReload,誰用誰知道。熱部署不僅界面開發需要,這是個通用需求,如果在服務端通過Dart實現一個,也是極好的。

        Flutter的構建工具並無太多亮點,而且因為Dart語言在Flutter中不支持反射(產物太大,增加包體積),業務架構實現上很多需要依賴於編譯時處理的技術,這對構建系統的能力有較大依賴的。換一個角度,因為這一領域尚沒有成熟方案,加上Dart的工程「友好」,可能實現由一種語言來統一前端開發,後端開發,以及構建和部署,真做到了會很酷!

        三. Flutter可以有些啥玩法

        討論前端要解決的幾個基礎要素問題,也討論了Flutter帶來的技術工具,結合這兩點,看看利用Flutter都能做些啥。

        1. 遠端通信

        「遠端通信」是一個做了抽象的概念,具體形式會根據「節點」的定義不同而不同。可以是指物理設備之間的通信(手機與伺服器),也可以指模塊之間(頁面與另一個頁面)的通信,還可以指組件之間(兩個StatefulWidget之間)的通信。因為在Flutter中「一切皆是Widget」,所以簡化的看,Flutter裡面大概分為兩種情形:面向伺服器的通信和組件(Widget)之間的通信。

        • 面向伺服器的通信:這方面有傳統的Restful,GraphQL,還有興起於「雲原生」概念的Serverless。藉助於Dart的能力延伸,Dart-Runtime可以成為Serverless的可選容器,那麼前後兩端都可以使用Dart來開發,如果再用Dart補足中間的構建部署pipeline,那麼可以搭建出一個很「雲原生」概念的應用程序開發流(dev flow):

        Flutter的跨端能力結合雲原生的彈性部署,前後端的實現可以放到一起,它們之間的調用也變得簡單自然,有理由相信這會是一個高效的開發方式。閑魚已經做了前期的探索,並在業務中嘗試落地。

        此外,GraphQL與Flutter也是值得嘗試的組合,GraphQL和React範式在理念上很對味口,但是我們並沒有嘗試過。

        • 組件之間的通信:Flutter提供的基礎業務編程組件是StatefulWidget和StatelessWidget,它們是按樹形結構來組織的,並提供了InheritedWidget來支持它們之間的通信,在通信方式可以總結出3種:
          1. Notify型:通知/監聽模式,Flutter提供了ValueNotifier和ChangeNotifier, 簡單方便,適用於輕量信息通信,參見Provider。
            1. Transmission型:數據傳輸模式,Dart提供了Stream來支持這種模式。使用靈活,擴展方便,幾乎是框架設計必備,參見BLoC。
              1. Invoke型: 介面調用模式,類似輕量RPC方式,在Flutter的應用架構設計中竟然很少見到。它確實有些重,但是有前面的模式沒有的優勢:它是雙向的。

              2. 狀態管理

              狀態管理是個大問題,它由兩個元素構成:狀態和處理狀態的邏輯。在代碼實現上,狀態就是數據,邏輯就是函數。當它們變得複雜的時候,解決的辦法其實就是拆分,然後再合理的組合。我嘗試從狀態和邏輯的拆分選擇上來列舉所有可能的解法:

              • 1. 狀態不拆,拆分邏輯: 這種做法的特點全局共用一個狀態結構體對象,所有狀態全部放在這個對象中,叫做「統一狀態管理」。只有一個數據對象,就消除了各個處理邏輯之間信息共享問題,邏輯內部沒有狀態,變得非常的純粹(比如純函數來實現),再將邏輯以合適的方式組合成一個整體,實現上界限清晰,簡單優雅,代表的方案就是Redux。 如果採用這種設計方案,推薦使用函數式風格來實現,這倒不是因為函數式「更高效」,「更優雅」之類的,而是它與函數式的思路十分的契合,在實現上更容易把握住思路。用面向對象來實現也並沒有問題,最後的效果取決於你所面臨的工程環境和用戶。 這種狀態管理好處顯而易見:一處狀態發生改變,不需要到處發事件同步。但是如果用在複雜大業務上面(比如一個有數十個頁面流程的業務產品),狀態必定是複雜的,狀態結構體必然是龐大的。Redux的方式很好的管理了邏輯,如果要管理一個統一龐大的狀態數據,也許內存級別的SQL是個不錯的主意,GraphQL-Client給了我們啟發,我們也正在嘗試實踐。

              • 2. 邏輯不拆,拆分狀態: 我把這種叫做「步進狀態管理」,實際上這類似於狀態機模式。但如果要真正使用,狀態必須是有限的,而且不能經常變動。這與互聯網持續多變的業務需求實際是不符合的,所以採用這種方式的設計幾乎沒有。但在一些很嚴肅的業務場景中,比如交易流程,一旦定下來就不容易變動。這時,步進狀態管理就很合適了。

              • 3. 同時拆分邏輯和狀態: 這是容易想到方案,在更細的粒度上,將狀態和它對應的處理邏輯拆分打包,變成更小的域(scope),然後統一協調這些子域(subModel),我把這種叫做「組合狀態管理」。進一步的方案可以統一定義subModel的基礎行為,然後引入調度器來協調管理它們,subModel之間還可以共享上下文來共享信息等等。 這種思路形式自由,可以採用的實現方式很多,經典的面向對象當然不在話下,scoped_model採用的就是這種思路,scoped_model實現的簡單易懂,同時能力也比較有限。當然也可以採用函數式的方式,高階函數+閉包也能很好的實現,但是圈內沒有看到有相關的設計實現。還有一點,Dart提供了Mixin特性,通過這個特性,可以得到更簡潔的實現方案。比如,可以沉澱很多特定的Model,然後通過with選擇組合到業務Model中來(參考Flutter Framework中WidgetsBinding的實現)。目前flutter-hook在做這方面的探索,flutter-hook看起來有些迷惑,其核心就是利用了Dart的Mixin特性來組合狀態。

              3. 界面管理

              Flutter使用了響應式UI,目的就是讓業務開發減少界面的管理工作,只要提供好頁面「描述」就行了。雖然Flutter內建了類似Virtual Dom的Diff機制,但是,做這個Diff也是要費性能的,如果我們在框架設計上能內建的把Diff工作提前到數據層,是不是可以提升性能呢?

              我們嘗試了幾種方法,受制於在Flutter中Dart不能反射,效果不理想,也許後續生態完善之後會有好的解法。

              在UI開發中,Flutter一直有一個隱隱的聲音就是動態化,官方好像是「忽略」的,這裡也不談了。

              4. 生命周期

              Flutter通過StatefulWidget給業務開發提供了基礎的生命周期管理。組件生命周期的設計是隨著業務場景的不同而不同的,我自己的理解,設計生命周期要從兩點出發:一是組件從誕生到消亡的時間線,二是組件在場景中所擁有的權益和所承擔的責任。生命周期的擴展原點是StatefulWidget,因業務場景不同而擴展不同,很難展開講。

              舉個例子,如果使用原生Flutter開發(或者叫純Flutter開發),StatefulWidget所提供的生命周期是足夠的。但是如果要做混合開發,引入混合棧後,顯然就不夠用了。這時候就需要提供新的組件來擴展生命周期,更好的滿足混合場景的開發。當時我在做混合棧的時候並沒有能理解到這一點。

              四. 結語

              本篇從分析前端開發需要面對的幾個基礎核心問題入手,結合Flutter帶來的技術工具,嘗試結構化的分析Flutter在業務開發中可能的技術選擇和探索方向。當然,技術同學既要仰望星空,還需要腳下看。

              對於Flutter開發中的熱點技術問題,歡迎關注閑魚技術公眾號的其他文章,或者加入我們,和閑魚一起做一點不一樣的技術!

              發佈於 01-22繼續瀏覽內容知乎發現更大的世界打開Chrome繼續暗落亭苦來暗落亭苦來這兒沒有什麼值得看的東西了

              我還真挺喜歡Flutter,也成功轉職了。

              我覺得我沒有成見,先從事Android,後來學React Native,再後來才學的Flutter。

              對比優劣,不多說,得罪人。但回答了題主的反問吧。

              代碼嵌套從一開始是不太習慣,現在已經接受。

              原因大概有幾點:

              1、一覽代碼並沒有多少意義。改代碼也好,改bug也好,不需要一覽幾百行代碼。寫好注釋,快速找到控制項位置,其實真的要讀要看的代碼,不會太多。至於截圖裡的代碼,一眼就能看出是什麼在幹什麼了。可能開始不習慣。

              2、代碼量在減少。我實際對比了下代碼量,Flutter遠遠小於Android原生。

              估計題主是web出身,所以對強大的css熟悉了。我作為原生開發,被xml折磨已久。


              我還真挺喜歡Flutter,也成功轉職了。

              我覺得我沒有成見,先從事Android,後來學React Native,再後來才學的Flutter。

              對比優劣,不多說,得罪人。但回答了題主的反問吧。

              代碼嵌套從一開始是不太習慣,現在已經接受。

              原因大概有幾點:

              1、一覽代碼並沒有多少意義。改代碼也好,改bug也好,不需要一覽幾百行代碼。寫好注釋,快速找到控制項位置,其實真的要讀要看的代碼,不會太多。至於截圖裡的代碼,一眼就能看出是什麼在幹什麼了。可能開始不習慣。

              2、代碼量在減少。我實際對比了下代碼量,Flutter遠遠小於Android原生。

              估計題主是web出身,所以對強大的css熟悉了。我作為原生開發,被xml折磨已久。


              我們小團隊的實際flutter項目,三個工具app,一個閱讀app,一個聊天app,一個解謎小遊戲。

              全部雙端上線(遊戲暫時沒版號只上了iOS )

              減少一半的開發工作量。最最最重要的是性能和原生幾乎沒有差別,除了前兩個項目出現其他回答中的無厘頭崩潰(基本是原生crash或者dispose後setState出問題),後面幾個app都比較順利,我們是從flutter 1.5.* 開始接觸的,當時為了給app加廣告整整搞了一個星期,現在已經很nice了,platform view好用。

              嗯,flutter真的香,嵌套UI代碼是個問題,不過 IDE 應該都有wrap 和 extract ,也比較容易解決這個問題。接受這種設定後,你會發現寫起來很帶感。github上這麼火的情況下,建議不要只看個表面就做出判斷。


              因為暫時沒更好的選擇,其實很多人喜歡flutter不是喜歡dart,而是喜歡skia。


              推薦閱讀:
              相关文章