#flutter #dart #inheritance #charts #bloc
#трепетать #дротик #наследование #Диаграммы #блок
Вопрос:
Тема: Что мне нужно сделать, чтобы «наследовать» _flDetailData от EventBloc
Два файла, перечисленные ниже LineChartEvents и EventBloc, настроены для отображения линейного графика fl_charts. LineChartEvents-это страница отображения, и она предназначена для получения данных из подпрограммы getChartData()блока событий
Страница LineChartEvents отображает линейную диаграмму с использованием данных, хранящихся в List _flDetailData, после выполнения
ChartData( startDate: '1638700000000', endDate: '2638700000000', ).getChartData();
в init() — но он всегда пуст.
Подпрограмма EventBloc getChartData() успешно извлекает данные из firestore и заполняет список _flDetailData внутри EventBloc точками FLSPOT.
Этот код выполняется, но _flDetailData пуст, когда я пытаюсь использовать его в build().
Пожалуйста, помогите
Доброе утро, день или вечер и с наилучшими пожеланиями,
Джаз
Спасибо
PS: у меня нет сервера для ссылки, поэтому код находится в строке ниже
======================= События линейного графика ========================
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:se_app/blocs/event_rollup_bloc.dart'; import 'package:provider/provider.dart'; import 'package:se_app/pages/charts/chart_data.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:se_app/pages/charts/chart_data'; class LineChartEvents extends StatefulWidget { const LineChartEvents({Key? key}) : super(key: key); @override _LineChartEventsState createState() =gt; _LineChartEventsState(); } class _LineChartEventsState extends Statelt;LineChartEventsgt; { Listlt;Colorgt; gradientColors = [ const Color(0xff23b6e6), const Color(0xff02d39a), ]; List _data = []; Listlt;FlSpotgt; flData = []; int index = 0; int _duration = 0; String _eventTitle = ''; int _timestampInt = 0; String _timestampIntStr = ''; String _dateNowStr = ''; Timestamp _timestamp = Timestamp.now(); int _day = 0; int _month = 0; int _year = 0; int _hour = 0; int _minute = 0; int _seconds = 0; Listlt;FlSpotgt; _flDetailData = []; @override initState() { super.initState(); ChartData( startDate: '1638700000000', endDate: '2638700000000', ).getChartData(); } bool showAvg = false; Future _getDate() async { final DateTime _nowDT = DateTime.now(); _timestamp = Timestamp.now(); _timestampInt = Timestamp.now().millisecondsSinceEpoch; _timestampIntStr = _timestampInt.toString().substring(0, 13); final dateStrSegments = _dateNowStr.split('-'); if (dateStrSegments.length == 6) { _year = int.tryParse(dateStrSegments[0])!; _month = int.tryParse(dateStrSegments[1])!; _day = int.tryParse(dateStrSegments[2])!; _hour = int.tryParse(dateStrSegments[3])!; _minute = int.tryParse(dateStrSegments[4])!; _seconds = int.tryParse(dateStrSegments[5])!; } } Duration swapAnimationDuration = const Duration(milliseconds: 150); Curve swapAnimationCurve = Curves.linear; @override Widget build(BuildContext context) { double w = MediaQuery.of(context).size.width; double h = MediaQuery.of(context).size.height; return Container( color: Colors.blueGrey, child: Flex( direction: Axis.vertical, children: [ Container( color: Colors.blueGrey, width: w * .6, height: 42, child: ElevatedButton( style: ElevatedButton.styleFrom( elevation: 8, primary: showAvg ? Colors.black : Colors.white.withOpacity(0.5)), onPressed: () { setState(() { showAvg = !showAvg; }); }, child: Text( showAvg ? 'Per Day Average' : 'Per Day Detail', style: TextStyle( fontSize: 24, color: showAvg ? Colors.white.withOpacity(0.5) : Colors.black), ), ), ), AspectRatio( aspectRatio: 1.70, child: Container( height: 120, decoration: const BoxDecoration( borderRadius: BorderRadius.all( Radius.circular(18), ), color: Color(0xff232d37)), child: Padding( padding: const EdgeInsets.only( right: 18.0, left: 12.0, top: 12, bottom: 12), child: LineChart( showAvg ? avgData(_flDetailData) : mainData(_flDetailData), ), ), ), ), ], ), ); } LineChartData mainData(flDetailData) { final EventRollupBloc eventRollupBloc = Provider.oflt;EventRollupBlocgt;(context); eventRollupBloc.getChartSeries(10, Timestamp(10000000, 1000000), 200, 20); return LineChartData( gridData: FlGridData( show: true, drawVerticalLine: true, getDrawingHorizontalLine: (value) { return FlLine( color: const Color(0xff37434d), strokeWidth: 1, ); }, getDrawingVerticalLine: (value) { return FlLine( color: const Color(0xff37434d), strokeWidth: 1, ); }, ), titlesData: FlTitlesData( show: true, rightTitles: SideTitles(showTitles: false), topTitles: SideTitles(showTitles: true), bottomTitles: SideTitles( showTitles: true, reservedSize: 22, interval: 1, getTextStyles: (context, value) =gt; const TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 16), getTitles: (value) { switch (value.toInt()) { case 2: return 'MAR'; case 5: return 'JUN'; case 8: return 'SEP'; } return ''; }, margin: 8, ), leftTitles: SideTitles( showTitles: true, interval: 1, getTextStyles: (context, value) =gt; const TextStyle( color: Color(0xff67727d), fontWeight: FontWeight.bold, fontSize: 15, ), getTitles: (value) { switch (value.toInt()) { case 1: return '10'; case 3: return '30'; case 5: return '50'; } return ''; }, reservedSize: 32, margin: 12, ), ), borderData: FlBorderData( show: true, border: Border.all(color: const Color(0xff37434d), width: 1), ), minX: 0, maxX: 20, minY: 0, maxY: 20, lineBarsData: [ LineChartBarData( spots: _flDetailData, // const [ // FlSpot(0, 3), // FlSpot(2.6, 2), // FlSpot(4.9, 5), // FlSpot(6.8, 3.1), // FlSpot(8, 4), // FlSpot(9.5, 3), // FlSpot(11, 4), // ], isCurved: true, colors: gradientColors, barWidth: 5, isStrokeCapRound: true, dotData: FlDotData( show: false, ), belowBarData: BarAreaData( show: true, colors: gradientColors.map((color) =gt; color.withOpacity(0.3)).toList(), ), ), ], ); } LineChartData avgData(flDetailData) { return LineChartData( lineTouchData: LineTouchData(enabled: false), gridData: FlGridData( show: true, drawHorizontalLine: true, getDrawingVerticalLine: (value) { return FlLine( color: const Color(0xff37434d), strokeWidth: 1, ); }, getDrawingHorizontalLine: (value) { return FlLine( color: const Color(0xff37434d), strokeWidth: 1, ); }, ), titlesData: FlTitlesData( show: true, bottomTitles: SideTitles( showTitles: true, reservedSize: 22, getTextStyles: (context, value) =gt; const TextStyle( color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 16), getTitles: (value) { switch (value.toInt()) { case 2: return 'MAR'; case 5: return 'JUN'; case 8: return 'SEP'; } return ''; }, margin: 8, interval: 1, ), leftTitles: SideTitles( showTitles: true, getTextStyles: (context, value) =gt; const TextStyle( color: Color(0xff67727d), fontWeight: FontWeight.bold, fontSize: 15, ), getTitles: (value) { switch (value.toInt()) { case 1: return '10k'; case 3: return '30k'; case 5: return '50k'; } return ''; }, reservedSize: 32, interval: 1, margin: 12, ), topTitles: SideTitles(showTitles: false), rightTitles: SideTitles(showTitles: false), ), borderData: FlBorderData( show: true, border: Border.all(color: const Color(0xff37434d), width: 1)), minX: 0, maxX: 11, minY: 0, maxY: 6, lineBarsData: [ LineChartBarData( spots: const [ FlSpot(0, 3.44), FlSpot(2.6, 3.44), FlSpot(4.9, 3.44), FlSpot(6.8, 3.44), FlSpot(8, 3.44), FlSpot(9.5, 3.44), FlSpot(11, 3.44), ], isCurved: true, colors: [ ColorTween(begin: gradientColors[0], end: gradientColors[1]) .lerp(0.2)!, ColorTween(begin: gradientColors[0], end: gradientColors[1]) .lerp(0.2)!, ], barWidth: 5, isStrokeCapRound: true, dotData: FlDotData( show: false, ), belowBarData: BarAreaData(show: true, colors: [ ColorTween(begin: gradientColors[0], end: gradientColors[1]) .lerp(0.2)! .withOpacity(0.1), ColorTween(begin: gradientColors[0], end: gradientColors[1]) .lerp(0.2)! .withOpacity(0.1), ]), ), ], ); } }
=========================================================
====================== EventBloc ========================
import 'package:charts_flutter/flutter.dart' as charts; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:se_app/blocs/profile_bloc.dart'; import 'package:se_app/models/charting_data.dart'; import 'package:shared_preferences/shared_preferences.dart'; // import 'package:fl_chart/fl_chart.dart'; class EventBloc extends ChangeNotifier { init() { // getEventLength(); getData(); } EventBloc() { // getEventLength(); getData(); } String data = ''; String _date = ''; String get date =gt; _date; List _data = []; List get eventData =gt; _data; List _filteredData = []; List get filteredData =gt; _filteredData; bool _hasData = false; bool get hasData =gt; _hasData; int _lastEventTimestampInt = 0; String _lastEventType = ''; Timestamp _timestamp = Timestamp.now(); int _stopTimestampInt = 0; int _timestampNowInt = 0; int _eventDurationInt = 0; String _durationDateStr = ''; String _timestampNowIntStr = ''; String _stopTimestampStr = ''; int _startEventTS = 0; int _stopEventTS = 0; String _eventDurationStr = ''; // bool _emoBool = false; // charting series vars Listlt;charts.Seriesgt; seriesList = []; bool animate = false; int _duration = 0; int _idx = 0; int _upperRangeTS = 0; int _lowerRangeTS = 0; DateTime _upperRangeDT = DateTime.now(); DateTime _lowerRangeDT = DateTime.now(); int _day = 0; int _month = 0; int _year = 0; int _hour = 0; int _minute = 0; int _seconds = 0; String _eventType = 'Ready'; String _uid = ''; String _dateStrDDMMYYYYHHMMSS = 'DDMMYYYYHHMMSS'; String sessionDuration = ''; int sessionCost = 0; int _eventLength = 0; int get eventLength =gt; _eventLength; int _savedNlength = 0; int get savedNlength =gt; _savedNlength; int _eventFinalLength = 0; int get eventFinalLength =gt; _eventFinalLength; Future getData() async { // TODO: JME #1 - final SharedPreferences _sp = await SharedPreferences.getInstance(); _uid = _sp.getString('uid')!; // setEventDurationString(); QuerySnapshot snap = await FirebaseFirestore.instance .collection('event') .where("uid", isEqualTo: _uid) .orderBy("timestamp", descending: false) .limit(1000) .get(); var x = snap.docs; _data.clear(); for (var f in x) { _data.add(f); } // _data.sort((a, b) =gt; a['timestamp'].compareTo(b['timestamp'])); notifyListeners(); } Future saveData(eventType, time) async { // TODO: JME #1 - SharedPreferences sp = await SharedPreferences.getInstance(); String? _uid = sp.getString('uid'); final ProfileBloc pb = ProfileBloc(); _timestampNowInt = Timestamp.now().millisecondsSinceEpoch; _timestampNowIntStr = _timestampNowInt.toString(); await FirebaseFirestore.instance.collection('event').doc().set( { "uid": _uid, "timestamp": _timestampNowIntStr, "year": _year, "month": _month, "day": _day, "hour": _hour, "minute": _minute, "seconds": _seconds, "eventType": eventType }, SetOptions(merge: false), ); // _emoBool = eventType.toString().substring(0, 3) == 'Emo'; if (eventType == 'Live' || eventType == 'Smoke') { //TODO: JME EMO amp;amp; _emoBool != true) { _lastEventTimestampInt = _timestampNowInt; _lastEventType = eventType; } if (eventType == 'Stop' || eventType == 'Complete') { //TODO: JME Emo - || _emoBool} { setEventDurationString(); await FirebaseFirestore.instance.collection('eventRollup').doc().set( { "uid": _uid, "timestamp": _timestampNowIntStr, // "duration": _emoBool ? '0' : _eventDurationStr, "duration": _eventDurationStr, "year": _year, "month": _month, "day": _day, "hour": _hour, "minute": _minute, "seconds": _seconds, // "eventType": _emoBool ? eventType : _lastEventType "eventType": _lastEventType }, SetOptions(merge: false), ); // .then( // //TODO: JME #1 (value) =gt; {pb.saveStatistics()}, // ); // set eventTypes to current event // _eventType = ''; // _lastEventType = ''; // _lastEventTimestampInt = 0; } // getData(); } Future setEventDurationString() async { // _eventDurationStr = _duration.toString(); _stopTimestampInt = Timestamp.now().millisecondsSinceEpoch; _eventDurationInt = _timestampNowInt - _lastEventTimestampInt; String aStr = DateFormat('yyyy-mm-dd-hh-mm-ssmmm') .format(DateTime.fromMillisecondsSinceEpoch(_eventDurationInt)); _eventDurationStr = _eventDurationInt.toString(); // split out date segments toInts for storage // reason is to speed up queries for charting // by day month and year final dateStrSegments = aStr.split('-'); if (dateStrSegments.length == 6) { _year = int.tryParse(dateStrSegments[0])!; _month = int.tryParse(dateStrSegments[1])! 1; _day = int.tryParse(dateStrSegments[2])!; _hour = int.tryParse(dateStrSegments[3])!; _minute = int.tryParse(dateStrSegments[4])!; _seconds = int.tryParse(dateStrSegments[5].substring(0, 2))!; // } } Future deleteEvent(uid, timestamp) async { FirebaseFirestore.instance .collection('event/$timestamp') .doc('$uid$timestamp') .delete(); getData(); } //charting routines void setRange(_startTimestamp, _duration, _period) { // Timestamp _ts = Timestamp.now(); int _tsInt = Timestamp.now().millisecondsSinceEpoch; String _tsStr = Timestamp.now().toString(); DateTime _tsDate = Timestamp.now().toDate(); var now = DateTime.now(); var _lowerRange = now.subtract(Duration(days: chartPeriodDays[_idx] * _duration)); int _durMS = chartPeriod[_idx] * _duration; _upperRangeTS = _tsInt; } Future getChartSeries( _period, _startTimestamp, _duration, _pagingListSize) async { if (chartPeriod.contains(_period)) { _idx = chartPeriod.indexOf(_period); setRange(_startTimestamp, _duration, _period); } else { //TODO: implement custom range // return default _period of a week in 7 stacks _period = 'Week'; _idx = 2; _duration = 1; _pagingListSize = 100; setRange(_startTimestamp, _duration, _period); } // get user uid SharedPreferences sp = await SharedPreferences.getInstance(); String? _uid = sp.getString('uid'); // get data gt;=lt; range // setEventDurationString(); QuerySnapshot snap = await FirebaseFirestore.instance .collection('event') .where("uid", isEqualTo: _uid) .orderBy("timestamp", descending: true) .get(); var x = snap.docs; _data.clear(); for (var f in x) { _data.add(f); } // _data.sort((a, b) =gt; b['timestamp'].compareTo(a['timestamp'])); // notifyListeners(); } } }