前言
我們在很流行的狀態(tài)管理庫 MobX 是怎么回事?介紹了 MobX 的基本概念和簡單的計數(shù)器示例。本篇我們引入一個非??犰诺膱D表插件庫來講解 MobX 網(wǎng)絡請求后渲染曲線。
MobX 驅(qū)動 UI
MobX 驅(qū)動 UI 時非常簡單,使用 flutter_mobx 插件后,簡化到只需要使用 Observer 的 builder 屬性包裹依賴狀態(tài)數(shù)據(jù)的子組件即可。只要子組件中有依賴狀態(tài)數(shù)據(jù),在狀態(tài)發(fā)生改變后就會自動刷新??梢哉f,MobX 大大簡化了狀態(tài)管理的使用,使得我們可以專注于業(yè)務代碼,而無需關心狀態(tài)和 UI 界面之間的聯(lián)系。
Observer(
builder: (_) => Text(
'${_counter.value}',
style: const TextStyle(fontSize: 20),
),
),
因此,MobX 本身太簡潔了(????)!并沒有什么太多可以介紹的,但是如果說要實現(xiàn)更復雜的狀態(tài)管理的話,還需要有別的方式,這個留在我們下一篇來介紹。
圖表插件庫 fl_chart
pub 上提供了不少圖標插件庫,其中 fl_chart 是最為流行的之一,我們來看看官方的示例,在手機上能夠?qū)崿F(xiàn)這樣的效果已經(jīng)十分酷炫了!示例工程中提供了所有已經(jīng)支持的圖表的示例,我們只需要按照示例進行修改就可以繪制我們自己的圖表。



UI 構(gòu)建
我們以曲線圖為例,通過后端數(shù)據(jù)繪制一條曲線。先來構(gòu)建曲線 UI。
class LineChartDemo extends StatelessWidget {
LineChartDemo({Key? key}) : super(key: key);
final ChartStore store = ChartStore();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('曲線')),
body: Observer(
builder: (context) => LineChart(
sampleData1(store.lineYData),
swapAnimationDuration: const Duration(milliseconds: 250),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
store.featchLineData();
},
child: Icon(Icons.refresh, color: Colors.white),
),
);
}
//...
}
曲線繪制的關鍵代碼是以狀態(tài)數(shù)據(jù)lineYData(Y 軸數(shù)據(jù))作為曲線的源數(shù)據(jù),從而使得狀態(tài)數(shù)據(jù)更新后可以自動渲染曲線。下面簡要介紹一下曲線圖的組成:
LineChartData sampleData1(List<double> yData) => LineChartData(
lineTouchData: lineTouchData1,
gridData: gridData,
titlesData: titlesData1,
borderData: borderData,
lineBarsData: lineBarsData1(yData),
minX: 0,
maxX: 15,
maxY: yData
.reduce((value, element) => value < element ? element : value)
.toDouble() +
1.0,
minY: yData
.reduce((value, element) => value > element ? element : value)
.toDouble() -
1.0,
);
LineChartData是曲線圖數(shù)據(jù)類,包括了如下部分:
-
lineTouchData:數(shù)據(jù)觸點配置數(shù)據(jù),即觸摸到數(shù)據(jù)點后如何顯示; -
gridData:網(wǎng)格數(shù)據(jù); -
titlesData:上下左右四個方位的標題欄(坐標軸欄)數(shù)據(jù),可以根據(jù)自己需要配置坐標軸顯示以及標題; -
borderData:邊框數(shù)據(jù),及是否要顯示邊框,以及如何顯示邊框; -
lineBarsData:數(shù)據(jù)點數(shù)組,可以在同一個圖表中顯示多條曲線。 -
minX,maxX,minY和MaxY:即 X 軸和 Y 軸的最大最小值范圍,可以根據(jù)需要設置范圍,比如本篇X 軸0-15,而 Y 軸則是根據(jù)返回值設置最大最小值,以保證曲線顯示在屏幕范圍內(nèi)。
再來看一下曲線數(shù)據(jù)點代碼,這里我們對各個屬性都加了注釋了,就無需再介紹了,實際可以根據(jù)需要返回多條曲線和設置曲線的樣式。
List<LineChartBarData> lineBarsData1(List<double> yData) {
double x = 1;
return [
LineChartBarData(
//曲線還是折線
isCurved: true,
//線條顏色
colors: [const Color(0xff4a99fa)],
//線粗細
barWidth: 2,
//是否圓形筆頭
isStrokeCapRound: true,
//是否顯示點數(shù)據(jù)
dotData: FlDotData(show: true),
//圖形覆蓋區(qū)域是否顯示
belowBarData: BarAreaData(show: true),
//坐標(x,y) 點集合
spots: yData.map((value) {
FlSpot spot = FlSpot(x, value.toDouble());
x += 2;
return spot;
}).toList(),
),
];
}
其他代碼基本上是從官方的樣例復制過來修改的,可以參考官網(wǎng)示例或本例的源代碼:MobX狀態(tài)管理代碼(運行時請同時運行后端代碼:配套后端代碼(基于 ExpressJs))。
狀態(tài)管理代碼
有了上一篇利用 VSCode 的代碼模板提高 MobX 的編碼效率介紹的代碼模板神器,編寫狀態(tài)代碼相當輕松。只需要修改狀態(tài)對象類型、名稱、初始值,然后實現(xiàn)獲取后端數(shù)據(jù)的 action 即可。代碼如下:
import 'package:mobx/mobx.dart';
import 'chart_service.dart';
part 'chart_store.g.dart';
class ChartStore = ChartStoreBase with _$ChartStore;
abstract class ChartStoreBase with Store {
@observable
List<double> lineYData = [0, 0, 0, 0, 0, 0, 0];
@action
Future<void> featchLineData() async {
var response = await ChartService.getLines();
if (response?.statusCode == 200) {
lineYData =
List<double>.from(response.data.map((e) => e.toDouble()).toList());
}
}
}
實際上自己寫的狀態(tài)代碼才4行而已!
運行效果
運行效果如下,實際開發(fā)過程中可以根據(jù)項目需要更改曲線樣式。

總結(jié)
從本篇我們更加能夠體會 MobX 的簡潔之處,真正地做到了狀態(tài)和 UI 分離以及無感知刷新。通過MobX 的代碼生成器和模板代碼可以大大減少我們的編碼量,提高效率。本篇我們還引入了 fl_chart 這個效果酷炫的圖表插件,這個插件基本上能夠滿足我們基本的線條圖、柱狀圖、散點圖和餅圖的圖表需要。