文 / Paul Halliday, developer.school 創始人
眾所周知,狀態管理是每個軟件項目都需要持續迭代更新的方向。它並不是一個「一次性」的工作,
而需要不斷確保你遵循的最佳實踐能夠讓你的工程保持良好的可維護性。
要在 Flutter 中高效地使用 MobX ,需要遵循以下原則:
- 我們能訪問任意狀態中的可觀察對象(即在我們應用運行過程中發生變化的變量)。
- 我們可以在 View 中展示這些狀態,並響應 Action 意圖。
- 我們可以修改狀態,從而更新可觀察對象以及相應的 View。
那么它的優勢在哪呢?答案是,通過 MobX 完成這一切將會變得超級簡單!codegen 工具可以幫我們完成絕大部分模版化的工作。
初始化項目
讓我們從創建一個全新的 Flutter 工程開始吧:
# New Flutter project
$ flutter create f_mobx && cd f_mobx
# Open in VS Code
$ code .
下一步,我們得在 pubspec.yaml
中拉取一些依賴 (dependencies
與 dev_dependencies
):
dependencies:
flutter:
sdk: flutter
mobx:
flutter_mobx:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.3.1
mobx_codegen:
之后我們可以在 main.dart
中創建一個全新的 MaterialApp
以放置我們的 CounterPage
。
import 'package:f_mobx/pages/counter_page.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: CounterPage(),
);
}
}
下一步,我們需要在 lib/pages/counter_page.dart
中創建 CounterPage
,並完成用戶界面的構建。其中包括了一個增加按鈕和一個減少按鈕。
import 'package:flutter/material.dart';
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Flutter and MobX'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter',
style: TextStyle(fontSize: 30.0),
),
Text(
'0',
style: TextStyle(fontSize: 42.0),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.add),
label: Text('Add'),
onPressed: () {},
),
FlatButton.icon(
icon: Icon(Icons.remove),
label: Text('Remove'),
onPressed: () {},
),
),
],
)
],
),
));
}
}
創建計數器的狀態
太棒了!我們現在已經在 lib/store/counter/counter.dart
創建好了我們的計數器。現在,讓我們來看看代碼,逐行進行解釋:
import 'package:mobx/mobx.dart';
// This is our generated file (we'll see this soon!)
part 'counter.g.dart';
// We expose this to be used throughout our project
class Counter = _Counter with _$Counter;
// Our store class
abstract class _Counter with Store {
@observable
int value = 1;
@action
void increment() {
value++;
}
@action
void decrement() {
value--;
}
}
- 我們導入了
mobx.dart
,這樣就可以訪問 Store 以及其他功能了。 - 接下來,我們使用了
part
語法組合此類的自動生成的部分。我們暫時還沒使用到生成器,但是別擔心,我們將會在下一個部分進行這個操作。 - 接下來,我們將暴露
Counter
類,該類將與生成的與 MobX 綁定的_$Counter
類一起使用。 - 最后,我們使用 Store 類創建一個
_Counter
,並定一個@observable
屬性和@actions
以確定 Store 可以與之交互的區域。
MobX 已經幫我們做了絕大部分繁瑣的事情,所以我們不需要關心底層是如何實現的。
現在我們已經有了 Counter
類,讓我們在終端的該工程目錄下通過下面的命令運行 build_runner
和 mobx_codegen
:
$ flutter packages pub run build_runner watch
我們現在應該可以看到生成的 counter.g.dart
文件。它看上去類似下面這樣:
part of 'counter.dart';
mixin _$Counter on _Counter, Store {
final _$valueAtom = Atom(name: '_Counter.value');
@override
int get value {
_$valueAtom.reportObserved();
return super.value;
}
@override
set value(int value) {
_$valueAtom.context.checkIfStateModificationsAreAllowed(_$valueAtom);
super.value = value;
_$valueAtom.reportChanged();
}
final _$_CounterActionController = ActionController(name: '_Counter');
@override
void increment() {
final _$actionInfo = _$_CounterActionController.startAction();
try {
return super.increment();
} finally {
_$_CounterActionController.endAction(_$actionInfo);
}
}
@override
void decrement() {
final _$actionInfo = _$_CounterActionController.startAction();
try {
return super.decrement();
} finally {
_$_CounterActionController.endAction(_$actionInfo);
}
}
}
這些東西,我們都不需要自己來實現!是不是很棒呀?
與 Store 進行綁定
接下來,我們需要讓 counter_page.dart
綁定到 Counter store。讓我們再次看看它長什么樣,然后進行深入探索:
import 'package:flut_mobx/store/counter/counter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
class CounterPage extends StatelessWidget {
final Counter counter = Counter();
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Flutter and MobX'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter',
style: TextStyle(fontSize: 30.0),
),
Observer(
builder: (_) =>
Text('${counter.value}', style: TextStyle(fontSize: 42.0)),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.add),
label: Text('Add'),
onPressed: counter.increment,
),
FlatButton.icon(
icon: Icon(Icons.remove),
label: Text('Remove'),
onPressed: counter.decrement,
),
],
)
],
),
));
}
}
讓我們深入研究一下:
- 我們導入了
flutter_mobx
以及我們的 Counter store,所以之后我們可以用到他們。 - 接下來,我們初始化了
Counter
,並將其命名為counter
,之后我們就可以輕松監聽這個可觀察對象的值,或是發出actions:final Counter counter = Counter()
; - 我們使用 Observer 監聽
counter.value
的值。 - 我們將 onPressed 事件綁定到
counter.increment
和counter.decrement
,它們會將action
發送到 Store。
上面這些代碼結合起來就完成了我們小型的計數器應用!
總結
希望這篇 MobX 的介紹能夠幫到你。我目前仍在持續探索 Flutter 狀態管理的最佳實踐,所以我也非常期待將來能對該系列進一步的更新。
原文:https://developer.school/flutter-state-management-with-mobx/
注:文章 & 視頻本地化和發布已獲得作者本人授權
致謝
- 本文作者:Paul Halliday
- 中文字幕翻譯: Alex、鑫磊
- 文章翻譯:加康、鑫磊
- 頭圖:Lynn