Flutter與MobX的那些事

開始

在之前的一篇文章中,半行代碼 介紹到在 Flutter 裏面使用 MobX, 今天咱們就來聊聊 Flutter 和 MobX 的那些事。前端

這篇文章的大部份內容能夠在 MobX.dart 中看到更原汁原味的介紹。閱讀本篇文章閱讀約需 30 分鐘。react

咱們先來看看 MobX 是什麼,根據README的介紹數據庫

使用透明的函數響應式編程加強 Dart 程序中的狀態管理

是前端裏大名鼎鼎的 MobX.js 的 Dart 版本。編程

概念

那麼,MobX.Dart 有哪些概念,反應了本身函數響應式編程的特性呢?微信

這裏關係到 MobX 的 3 個重要概念:網絡

  • Observables: Observables 表示響應式的狀態。狀態很容易理解,就是應用程序裏面的狀態,或者數據。響應式,就是能夠感知到,可觀察到數據的變化,也就是咱們常常接觸到的 觀察者模式
  • Actions: Actions 就是一系列能夠引起狀態發生變化的動做
  • Reactions:上面提到狀態是可觀察的,那麼這裏的 Reactions 就是狀態的觀察者,狀態發生改變的時候,他們能夠收到數據變化的通知。

關於 Observables,還有一些更多的概念:架構

Computed Observables

顧名思義,被計算出來的 Observables。在一個應用中,咱們實際上有 2 種狀態,這裏分別稱爲 core-statederived-statecore-state 指的就是一個對象本來就存在的狀態,例如一我的有本身的firstname和lastname,姓和名是人固有的狀態。那麼 firstname + lastname,就動態的出來了咱們」姓名「的結果。這個就是咱們的 derived-state。固然這裏是一個很基礎的例子,現實中咱們的業務多是幾個固有屬性,經過一個複雜的計算算出了一個最終的結果。這個最終結果實際上也是這個對象的一種狀態,它也須要被感知到變化。框架

這裏套用 MobX 的一張圖來表示他的核心概念:less

image

show code

咱們來看看 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 結合在一塊兒。

  • Widget: UI,狀態的可視化表示
  • Store:處理狀態
  • Service:邏輯操做,包括複雜邏輯,網絡請求,本地數據庫存儲等等

最佳的代碼結構以下:

image

其中:

UI 層應該儘可能使用 StatelessWidgetObserver 結合, 減小 Widget 的 rebuild 次數,提高性能。

Store裏面放的 @observable 對象,由於 Dart 在 Flutter 是不能進行運行時反射的,因此複雜對象須要咱們本身進行 observable 的聲明。不然不會生效。當須要處理衍生狀態的時候,可用 computed 替代。

到這裏,其實咱們在使用 MobX 的時候能夠組織出職責分層很明確的函數響應式應用架構。可是不一樣的頁面如何持有 Store 對象,也成了一個問題,固然這個問題在全部的分層架構裏都存在。

最簡單的是直接寫單例的 store, 可是單例的弊端很是明顯。咱們須要的是在這幾個頁面這個對象是同一個,超出這個範圍,對象能夠銷燬,或者使用的是另外一個對象。很直接的咱們就會須要一個對象管理框架,即 依賴注入

針對這點,官方也給出了本身的建議,可使用 Provider 這個框架達到依賴注入的目的。在他的官方文檔介紹裏,也說本身是一個介於 DI 和 狀態管理之間的框架。在這篇文章就不贅述 Provider的使用,感興趣的朋友能夠查看:provider的文檔

小結

使用 MobX,咱們能夠快速的上手,用一種很簡便,容易組織的方式進行 Flutter 的狀態管理和代碼架構的統一。並且 Store 自然的分開能夠寫一堆。不會存在 Redux 頂級狀態管理難以分而治之的問題。對於異步場景的處理也比 Redux 簡單。比較推薦給你們。

請關注個人微信公衆號 【半行代碼】

相關文章
相關標籤/搜索