微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Syncfusion Flutter 实时折线图 - 来自 Streambuilder 的数据

如何解决Syncfusion Flutter 实时折线图 - 来自 Streambuilder 的数据

我正在尝试使用 pub.dev 创建实时折线图。它非常适合使用 API 绘制图表并立即获取所有数据。 我现在正在尝试的是绘制实时图表。目前,我的应用程序从设备读取心跳并显示每秒不断变化的 BPM 值。类似于以下屏幕截图:

enter image description here

上面的心脏图像是一个跳动的动画,根据读数,数字每秒都在变化。 下面的代码显示了我是如何做到这一点的。

class Reading extends StatefulWidget {
  Reading({Key key,this.device,this.char,this.allTags});

  final BluetoothDevice device;
  final BluetoothCharacteristic char;
  final List allTags;

  @override
  ReadingState createState() => ReadingState();
}

class ReadingState extends State<Reading> with WidgetsBindingObserver {
  int percent;
  Timer _timer;
  double count = 0;
  int tempElapsed = 0;
  String tempByte = "";

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addobserver(this);
    Wakelock.enable();
    _startTimer();
    // setup();
  }

  @override
  void dispose() {
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
  }

  stopReading(ctx,character) async {
    await character?.setNotifyValue(false);
    if ((widget?.allTags ?? []).length > 0) {
      sl<IDashboardProvider>().showTagPicker(context,widget?.allTags);
    } else {
      sl<IDashboardProvider>().navigatetoAnalysis(context);
    }
  }

  incrementCount() {
    if (this.count + 1 == READING_DURTION_IN_SECOND) {
      setState(() {
        count = READING_DURTION_IN_SECOND.todouble();
      });
      _timer.cancel();
      stopReading(context,widget.char);
    } else {
      setState(() {
        count = count + 1;
      });
    }
  }

  _startTimer() {
    _timer = Timer.periodic(
      Duration(seconds: 1),(Timer timer) => incrementCount(),);
  }

  _pauseTimer() {
    _timer.cancel();
  }

  showDialogFunction(context) {
    showDialog(
      context: context,builder: (BuildContext ctx) {
        return AlertDialog(
          title: new Text("Warning"),content: new Text(
              "Device disconnected,please try again connecting the device"),actions: <Widget>[
            new FlatButton(
              child: new Text("Ok"),onpressed: () {
                Navigator.of(ctx).pushAndRemoveUntil(
                    MaterialPageRoute(
                        builder: (context) => NewDevice(
                              deviceFor: 0,)),(Route<dynamic> route) => false);
              },),],);
      },);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);
    if (state == AppLifecycleState.resumed) {
      _startTimer();
    } else if (state == AppLifecycleState.paused) {
      _pauseTimer();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,automaticallyImplyLeading: false,centerTitle: true,title: Text("Activity"),backgroundColor: PRIMARY,body: Container(
        height: MediaQuery.of(context).size.height,child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
                SpinKitPumpingHeart(
                  color: PRIMARY,size: 30,SizedBox(
                  width: 10,widget?.char?.value == null
                    ? Container()
                    : StreamBuilder<Map>(
                        stream: widget?.char?.value,initialData: widget?.char?.lastValue,builder: (c,mainSnapshot) {
                          var value;
                          print("NOTES - device print - ${mainSnapshot?.data}");
                          value = mainSnapshot.data != null
                              ? mainSnapshot.data["value"]
                              : 0;
                          if (this.count >= 10 &&
                              tempElapsed != mainSnapshot.data["elspsed"] &&
                              tempByte != mainSnapshot.data["byte"]) {
                            sl<IDashboardProvider>()
                                .recordedData
                                .add(mainSnapshot.data["byte"].trim());
                            tempElapsed = widget?.char?.lastValue["elapsed"];
                            tempByte = widget?.char?.lastValue["byte"];
                            print(
                                "NOTES - recorded data list Length - ${sl<IDashboardProvider>().recordedData.length}");
                            print(
                                "NOTES - recorded data list - ${sl<IDashboardProvider>().recordedData}");
                          }

                          return RichText(
                            text: TextSpan(
                              children: <TextSpan>[
                                TextSpan(
                                  text: value.toString(),style: TextStyle(
                                      fontSize: 20,color: DARK_GREY,fontFamily: "HRVFont"),TextSpan(
                                  text: " bpm",style: TextStyle(
                                      fontSize: 16,color: MEDIUM_GREY,)
                              ],);
                        }),StreamBuilder<BluetoothDeviceState>(
                  stream: widget.device.state,initialData: BluetoothDeviceState.CONNECTING,snapshot) {
                    String text;
                    if (_timer.isActive)
                      switch (snapshot.data) {
                        case BluetoothDeviceState.disCONNECTED:
                          text = "disCONNECTED";
                          WidgetsBinding.instance.addPostFrameCallback(
                              (_) => showDialogFunction(context));
                          widget.device.disconnect();
                          _timer.cancel();
                          break;
                        default:
                          text = "UNKNowN";
                          break;
                      }
                    return Container();
                  },Text(
              "We are getting your data",style: TextStyle(fontSize: 20,color: DARK_GREY),Stack(
              alignment: Alignment.center,children: <Widget>[
                CircularPercentIndicator(
                  radius: 100.0,linewidth: 8.0,percent: (this.count / (READING_DURTION_IN_SECOND + 1)) * 1,center: new Text(
                    ((this.count / (READING_DURTION_IN_SECOND + 1)) * 100)
                            .toInt()
                            .toString() +
                        "%",style: new TextStyle(
                        fontWeight: FontWeight.bold,fontSize: 20.0),circularstrokeCap: CircularstrokeCap.round,progressColor: PRIMARY,SpinKitpulse(
                  color: PRIMARY,size: 80,

容器( 子项:SfCartesianChart( 工具提示行为:工具提示行为(启用:真), 主X轴:日期时间轴(), 系列:>[ Lineseries<_chartdata datetime>( 数据源:图表数据, xValueMapper: (_ChartData 数据,_) => data.x,yValueMapper: (_ChartData 数据,_) => data.y) ]),) ],); } }

我对如何添加实时折线图而不是简单数字感到困惑。流构建器提供 BPM 的值。我尝试按照以下步骤创建图表:Syncfusuion Example

最终创建了 2 个我认为不是最理想的变量。

Timer chartTimer;
int chartCount = 0;
List<_ChartData> chartData = <_ChartData>[];
Map<dynamic,dynamic> data;

void _updateDataSource(Timer chartTimer) {
    setState(() {
      chartData.add(_ChartData(
          x: DateTime.fromMillisecondsSinceEpoch(data['x']),y1: data['y1']));
      // if(chartData.length >= 20){
      //   chartData.removeAt(0);
      // }    
    });

    chartCount = chartCount + 1;
  }

然后尝试将以下内容添加到 streambuilder:

data = values[chartCount];
chartTimer = Timer.periodic(Duration(milliseconds: 3000),_updateDataSource); 

我从来没有得到任何结果,图表中也没有数据

解决方法

感谢您对我们的 Flutter 图表的关注。我们已经分析了您的查询并准备了以 StreamBuilder 为参考的折线图 sample,您可以根据需要进行更改。如果您需要任何进一步的帮助,也可以通过我们的 support forumsDirect-Tracfeedback 门户与我们联系。我们随时乐意为您提供帮助!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。