在之前的一篇文章中,半行代碼
介紹到在 Flutter 裏面使用 MobX
, 今天咱們就來聊聊 Flutter 和 MobX 的那些事。前端
這篇文章的大部份內容能夠在 MobX.dart 中看到更原汁原味的介紹。閱讀本篇文章閱讀約需 30 分鐘。react
咱們先來看看 MobX 是什麼,根據README的介紹數據庫
使用透明的函數響應式編程加強 Dart 程序中的狀態管理
是前端裏大名鼎鼎的 MobX.js
的 Dart 版本。編程
那麼,MobX.Dart 有哪些概念,反應了本身函數響應式編程的特性呢?微信
這裏關係到 MobX
的 3 個重要概念:網絡
觀察者模式
關於 Observables,還有一些更多的概念:架構
顧名思義,被計算出來的 Observables。在一個應用中,咱們實際上有 2 種狀態,這裏分別稱爲 core-state
和 derived-state
,core-state
指的就是一個對象本來就存在的狀態,例如一我的有本身的firstname和lastname,姓和名是人固有的狀態。那麼 firstname + lastname,就動態的出來了咱們」姓名「的結果。這個就是咱們的 derived-state
。固然這裏是一個很基礎的例子,現實中咱們的業務多是幾個固有屬性,經過一個複雜的計算算出了一個最終的結果。這個最終結果實際上也是這個對象的一種狀態,它也須要被感知到變化。框架
這裏套用 MobX
的一張圖來表示他的核心概念:less
咱們來看看 Mobx
的具體用法,套用 Flutter 默認的 計數器點擊 +1 的例子。異步
一個簡單的計數器能夠表示成一個可觀察的數字狀態,計數器表示爲 Counter 對象:
part 'counter.g.dart'; class Counter = CounterBase with _$Counter; abstract class CounterBase with Store { @observable int value = 0; @action void increment() { value++; } }
這裏,Mobx
須要藉助 builder_runner
這個庫生成對應的 _$Counter
類的代碼。具體能夠自行 Google。
那麼示例中計數器的值怎麼反應到 UI 呢?這裏就要藉助咱們 Flutter-MobX
裏的 Widget 啦
final counter = Counter(); // Instantiate the store Observer( builder: (_) => Text('${counter.value}', style: Theme.of(context).textTheme.display1, ), ),
這裏咱們使用了一個叫作 Observer
的 Widget, builder方法裏面把 counter 的 observable 對象的值做爲屬性傳給 Text。
這裏在調用 @action
的函數以後,counter 裏面的值變化後會自動體如今 UI 上。
這裏咱們能夠看到,使用了 MobX
,咱們能夠儘量的使用 StatelessWidget
,避免了 setState
的混亂。也提高了效率。
那麼如何使用 Reaction 完成對他的監聽呢,Reaction相關的函數有好幾個,這裏列舉幾個比較典型的:
ReactionDisposer autorun(Function(Reaction) fn)
當即執行 fn
import 'package:mobx/mobx.dart'; String greeting = Observable('Hello World'); final dispose = autorun((_){ print(greeting.value); }); greeting.value = 'Hello MobX'; dispose();
這裏會輸出
Hello World Hello MobX
ReactionDisposer reaction<T>(T Function(Reaction) predicate, void Function(T) effect)
監聽 predicate
裏面監聽 observable,當 predicate
返回了新的對象的時候,調用 effect
函數。
import 'package:mobx/mobx.dart'; String greeting = Observable('Hello World'); final dispose = reaction((_) => greeting.value, (msg) => print(msg)); greeting.value = 'Hello MobX'; // Cause a change dispose();
輸出:
Hello MobX
ReactionDisposer when(bool Function(Reaction) predicate, void Function() effect)
待條件的響應。在reaction
的基礎上加上 predicate
函數返回 true
使用了 MobX
,那麼咱們的代碼該如何組織呢?通常來講,咱們的 Store
會按照職責,分到每一個業務相關的 Store
去。
那麼,一個業務模塊,如何組織它和 UI、邏輯呢?官方給出了建議的方式。將 Widegt - Store - Service 結合在一塊兒。
最佳的代碼結構以下:
其中:
UI 層應該儘可能使用 StatelessWidget
和 Observer
結合, 減小 Widget 的 rebuild 次數,提高性能。
Store裏面放的 @observable
對象,由於 Dart 在 Flutter 是不能進行運行時反射的,因此複雜對象須要咱們本身進行 observable 的聲明。不然不會生效。當須要處理衍生狀態的時候,可用 computed
替代。
到這裏,其實咱們在使用 MobX
的時候能夠組織出職責分層很明確的函數響應式應用架構。可是不一樣的頁面如何持有 Store
對象,也成了一個問題,固然這個問題在全部的分層架構裏都存在。
最簡單的是直接寫單例的 store, 可是單例的弊端很是明顯。咱們須要的是在這幾個頁面這個對象是同一個,超出這個範圍,對象能夠銷燬,或者使用的是另外一個對象。很直接的咱們就會須要一個對象管理框架,即 依賴注入
針對這點,官方也給出了本身的建議,可使用 Provider
這個框架達到依賴注入的目的。在他的官方文檔介紹裏,也說本身是一個介於 DI 和 狀態管理之間的框架。在這篇文章就不贅述 Provider
的使用,感興趣的朋友能夠查看:provider的文檔
使用 MobX
,咱們能夠快速的上手,用一種很簡便,容易組織的方式進行 Flutter 的狀態管理和代碼架構的統一。並且 Store 自然的分開能夠寫一堆。不會存在 Redux
頂級狀態管理難以分而治之的問題。對於異步場景的處理也比 Redux 簡單。比較推薦給你們。
請關注個人微信公衆號 【半行代碼】