Flutter 入門與實戰(六十八):MobX 獲取網路資料來渲染酷炫的曲線

島上碼農發表於2021-08-30

這是我參與8月更文挑戰的第31天,活動詳情檢視:8月更文挑戰

前言

我們在Flutter 入門與實戰(六十六):聽說 MobX 很流行,進來了解一下?介紹了 MobX 的基本概念和簡單的計數器示例。本篇我們引入一個非常酷炫的圖表外掛庫來講解 MobX 網路請求後渲染曲線。

MobX 驅動 UI

MobX 驅動 UI 時非常簡單,使用 flutter_mobx 外掛後,簡化到只需要使用 Observerbuilder 屬性包裹依賴狀態資料的子元件即可。只要子元件中有依賴狀態資料,在狀態發生改變後就會自動重新整理。可以說,MobX 大大簡化了狀態管理的使用,使得我們可以專注於業務程式碼,而無需關心狀態和 UI 介面之間的聯絡。

Observer(
  builder: (_) => Text(
    '${_counter.value}',
    style: const TextStyle(fontSize: 20),
  ),
),
複製程式碼

因此,MobX 本身太簡潔了(??)!並沒有什麼太多可以介紹的,但是如果說要實現更復雜的狀態管理的話,還需要有別的方式,這個留在我們下一篇來介紹。

圖表外掛庫 fl_chart

pub 上提供了不少圖示外掛庫,其中 fl_chart 是最為流行的之一,我們來看看官方的示例,在手機上能夠實現這樣的效果已經十分酷炫了!示例工程中提供了所有已經支援的圖表的示例,我們只需要按照示例進行修改就可以繪製我們自己的圖表。 scatter_chart_sample_1.gif bar_chart_sample_2.gif pie_chart_sample_2.gif

UI 構建

我們以曲線圖為例,通過後端資料繪製一條曲線。先來構建曲線 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),
      ),
    );
  }
 //...
}
複製程式碼

曲線繪製的關鍵程式碼是以狀態資料lineYData(Y 軸資料)作為曲線的源資料,從而使得狀態資料更新後可以自動渲染曲線。下面簡要介紹一下曲線圖的組成:

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是曲線圖資料類,包括瞭如下部分:

  • lineTouchData:資料觸點配置資料,即觸控到資料點後如何顯示;
  • gridData:網格資料;
  • titlesData:上下左右四個方位的標題欄(座標軸欄)資料,可以根據自己需要配置座標軸顯示以及標題;
  • borderData:邊框資料,及是否要顯示邊框,以及如何顯示邊框;
  • lineBarsData:資料點陣列,可以在同一個圖表中顯示多條曲線。
  • minXmaxXminYMaxY:即 X 軸和 Y 軸的最大最小值範圍,可以根據需要設定範圍,比如本篇X 軸0-15,而 Y 軸則是根據返回值設定最大最小值,以保證曲線顯示在螢幕範圍內。

再來看一下曲線資料點程式碼,這裡我們對乜咯屬性都加了註釋了,就無需再介紹了,實際可以根據需要返回多條曲線和設定曲線的樣式。

List<LineChartBarData> lineBarsData1(List<double> yData) {
  double x = 1;
  return [
    LineChartBarData(
      //曲線還是折線
      isCurved: true,
      //線條顏色
      colors: [const Color(0xff4a99fa)],
      //線粗細
      barWidth: 2,
      //是否圓形筆頭
      isStrokeCapRound: true,
      //是否顯示點資料
      dotData: FlDotData(show: true),
      //圖形覆蓋區域是否顯示
      belowBarData: BarAreaData(show: true),
      //座標(x,y) 點集合
      spots: yData.map((value) {
        FlSpot spot = FlSpot(x, value.toDouble());
        x += 2;
        return spot;
      }).toList(),
    ),
  ];
}
複製程式碼

其他程式碼基本上是從官方的樣例複製過來修改的,可以參考官網示例或本例的原始碼:MobX狀態管理程式碼(執行時請同時執行後端程式碼:配套後端程式碼(基於 ExpressJs))。

狀態管理程式碼

有了上一篇Flutter 入門與實戰(六十七):教你一個讓編碼速度飛起的方法!介紹的程式碼模板神器,編寫狀態程式碼相當輕鬆。只需要修改狀態物件型別、名稱、初始值,然後實現獲取後端資料的 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());
    }
  }
}
複製程式碼

實際上自己寫的狀態程式碼才4行而已!

執行效果

執行效果如下,實際開發過程中可以根據專案需要更改曲線樣式。

曲線執行效果

總結

從本篇我們更加能夠體會 MobX 的簡潔之處,真正地做到了狀態和 UI 分離以及無感知重新整理。通過MobX 的程式碼生成器和模板程式碼可以大大減少我們的編碼量,提高效率。本篇我們還引入了 fl_chart 這個效果酷炫的圖表外掛,這個外掛基本上能夠滿足我們基本的線條圖、柱狀圖、散點圖和餅圖的圖表需要。

目前對於使用MobX還需要解決2個問題,那就是是否支援巢狀和多元件共享,我們接下來將介紹這部分內容。


我是島上碼農,微信公眾號同名,這是Flutter 入門與實戰的專欄文章,對應原始碼請看這裡:Flutter 入門與實戰專欄原始碼

??:覺得有收穫請點個贊鼓勵一下!

?:收藏文章,方便回看哦!

?:評論交流,互相進步!

相關文章