Flutter 開源狀態管理外掛一覽

語言: CN / TW / HK

楔子

話說孔乙己轉行做了程式設計師,聽聞近年來大前端比較火,也跟風學了一陣。什麼 Vue,React,Angular 都瞭解一點。這段時間,行業巨頭谷歌出了個 Flutter,號稱要一套程式碼搞定整個前端,孔乙己自然不願放過。

這天孔乙己逛到了掘金社群,裡面大佬太多,他怕自己太業餘露餡。知道不能和他們談天,便只好向初學者說話。有一回在我的評論區問道,“你學過 Flutter 麼?”我略略回了個表情。他說,“學過,……我便考你一考。Flutter 的狀態管理,怎樣寫的?”我想,水平和我一樣的人,也配考我麼?便沒有回訊息,不再理會。孔乙己等了許久,再一次評論道,“不能寫罷?……我教給你,記著!Flutter 狀態管理應該這樣寫。將來做高階工程師的時候,做架構要用。”我暗想我和高階工程師的等級還很遠呢,而且我們總監也從不用 Flutter 開發應用;又好笑,又不耐煩,懶懶的答他道,“誰要你教,不就是用一個 setState 方法麼?”孔乙己顯出極高興的樣子,發了一個 耶的勝利表情,點頭說,“對呀對呀!……狀態管理有 N 種寫法,你知道麼?”我自然是沒有回答,但他自己卻真的列了出來。

Provider

在 Pub 上最受歡迎的狀態管理外掛之一,憑藉簡潔、易用、高效能受到了很多 Flutter 開發者的喜愛,更是成為了官方首要推薦的狀態管理工具。外掛 pub 地址:Provider package。本質上, Provider 是在 InheritedWidget 基礎上的封裝,使用 Provider 具有如下特性:

  • 簡化資源的分配和銷燬;

  • 懶載入;

  • 減少了大量建立狀態管理相關類程式碼的工作;

  • 通用的方式去消費 InheritedWidget 共享的資料;

  • 對於複雜度顯著上升的監聽鏈路,提供了高可擴充套件性。

setState

最為初級、也是最簡單粗暴的狀態管理方法,官方的 Hello World 示例用的就是這種方式,優點是簡單,缺點嘛 —— 其他狀態管理的優點就是它的缺點,那些都是針對這種方式的缺點改進的。當然,也不是不能用,如果只是針對沒有子元件或子元件很少的情況,用 setState 也沒什麼問題。

InheritedWidget 和 InheritedModel

前面介紹的 ModelBinding 就是這種方式, Provider 其實也是這種方式。對 InheritedWidget 進行封裝,實現資料在元件樹上傳遞,進而達到狀態資料共享和區域性重新整理的目的。

Redux

類似 React 的狀態管理工具 Redux ,本質上是一個狀態容器,pub 地址: Flutter-Redux package 。關鍵在於提供了 3 種 Widget

  • StoreProvider :基礎 Widget ,它會把指定的 Redux 狀態資料( Redux Store ) 傳遞給需要的下級元件;

  • StoreBuilder :一個從 StoreProvider 獲取狀態的下級元件,它會將獲取到的狀態傳遞給一個返回 Widgetbuilder 方法。

  • StoreConnector :一個從最臨近的 StoreProvider 祖先元件獲取狀態的下級元件,然後利用 指定的 converter 將狀態轉換為 ViewModel 物件後給到 builder 方法。任何時候,狀態發出一個更改事件後,該元件會被自動重建,從而無需主動管理事件訂閱。

Fish Redux

閒魚出品的一個基於 Redux 的整體應用框架,對於構建大中型應用來說很合適,pub 地址:Fish-Redux package。與 Redux 的區別是,Fish Redux 是一個應用框架,解決了如應用分治、通訊、資料驅動、解耦等問題。作為一個應用框架,優點是可以為團隊建立一套統一的規範,當然缺點也有,比如對於小應用來說可能過於龐大,靈活性不足,可能會影響開閥發效率。

BLoC / Rx

一個基於 Stream / Observable 正規化的系列,關於介紹可以看官方的文件:Flutter BLoC。

GetIt

GetIt 實際上是一個基於狀態管理的服務管理工具,優點是不需要 BuildContext。如果想使用依賴注入、面向介面程式設計的方式來實現程式碼解耦和應用管理則十分適合。對應的 pub 包和文件如下:

  • GetIt package:基礎的服務管理工具,提供了容器幫助程式碼找到對應的服務提供物件。

  • GetIt Mixin:GetIt 的擴充套件,使得 GetIt 可以完全應用於狀態管理。

  • GetIt Hooks:GetIt 的另一個擴充套件,可以用於 flutter_hooks 的場景。

  • Flutter state management for minimalist :一篇介紹 Flutter 狀態管理與應用架構的文章,值得仔細閱讀。

MobX

基於觀察者模式和響應式模式的狀態管理庫,GitHub 地址: MobX 。 MobX 的目標是將應用的介面和響應式資料連線起來。這種方式是完全自動的,而且感覺很自然(類似雙向繫結)。對於開發者而言,只需要關注介面需要消費的響應式資料,而不用擔心保持二者的同步。

Flutter Commands

基於 ValueNotifier,使用命令模式實現的響應式狀態管理庫。最佳的實踐是與 GetIt 結合,也可以使用 Provider 或其他容器配合。pub 地址:Flutter Command。

Binder

基於 InheritedWidget 的狀態管理包,仿照的是 recoil,目標是想將業務、狀態和介面分離解耦,pub 地址:Binder package。

GetX

一個簡化的狀態管理解決方案,pub 地址:GetX package。GetX 是一個超輕量、但很強大的 Flutter 解決方案,提供了高效能的狀態管理,智慧依賴注入和快速可用的路由管理工具。GetX 由於簡化了很多實現程式碼,目前的流行度已經超過了 Provider。

States Rebuilder

States Rebuilder 是高效能,滿足預期和可控的狀態管理工具。支援可變和不可變的狀態,實現了嚴格的狀態控制,並且支援自動清除狀態。而且還可以在 StatelessWidget 中使用 setState (狀態資料模型類的 setState ,) 更新介面,同樣也支援無需 BuildContext 的頁面導航和訊息提示。GitHub 地址: States Rebuilder

尾聲

等到孔乙己寫完之後,我竟然有點驚到了,難道這些他都會?但礙於顏面,又不好意思問他。只好自己按照他寫的那些去搜了一下。至於他是不是都會,也就無從知道了!

總結

由於 Dart 語言和 Javascript 有很多共同之處,因此在 pub 上有很多類似 Javascript 的庫,譬如 Redux,MobX 等。實際上,沒有最好的狀態管理工具,只有最合適的狀態管理工具。具體如何選擇可以參考以下幾點:

  • 更新維護及時性:Flutter 本身的迭代速度很快,因此有些外掛如果不及時維護的話意味著你之後的程式碼全部需要更改,尤其是狀態管理這類涉及到整個應用架構的外掛。

  • 使用者數量:可以通過 pub 的評分和 Github 的評分來評估使用者的情況,使用人數不多意味著你可能會需要自己踩坑排雷,對於自己玩的話無所謂,但是對於產品開發就可能會影響整個產品的開發進度。

  • 團隊適應性:如果是你一個人開發,那可以忽略這一點,但是如果團隊有多人,那需要考慮一個大家都能夠快速上手的外掛。

  • 原生依賴度:有不少外掛是需要依賴原生的,而有些原生本身就是第三方的開原始碼,如果這些開原始碼停止維護了很可能導致 Flutter 的外掛也無法更新。因此,除非是官方外掛,對於第三方外掛要特別小心,如果第三方外掛依賴於原生甚至是第三方開原始碼,那麼就需要注意要慎重選擇。如果可以,儘可能選擇純 Dart 的外掛。