0

我在 Flutter 中使用 Firestore 和 Syncfusion Flutter Charts 时遇到问题。我正在从 firestore 查询一些文档,等待结果,所以函数必须是 Future,但我需要它是 a List,而不是 a Future<List>。这是我的代码:

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: SfCartesianChart(
        primaryXAxis: CategoryAxis(
          majorGridLines: const MajorGridLines(width: 0),
          axisLine: const AxisLine(width: 0),
        ),
        primaryYAxis: NumericAxis(
          majorGridLines: const MajorGridLines(width: 0),
          axisLine: const AxisLine(width: 0),
        ),
        plotAreaBorderWidth: 0,
        series: getData(),
      ),
    );
  }

  String getcurrentMonth() {
    DateTime date = DateTime.now();
    return DateFormat.MMMM().format(date).substring(0, 3);
  }

  List<String> getOtherMonths() {
    List<String> otherMonths = [];
    DateTime date = DateTime.now();
    for (var i = 1; i < 5; i++) {
      DateTime prev = DateTime(date.year, date.month - i, date.day);
      otherMonths.add(DateFormat.MMMM().format(prev).substring(0, 3));
    }
    return otherMonths;
  }

  Future<List<double>> getTotalByMonth() async {
    List<double> totals = [];
    DateTime date = DateTime.now();
    for (var i = 0; i < 5; i++) {
      var lastDay = DateTime(date.year, date.month - i + 1, 0);
      DateTime startOfMonth = DateTime(date.year, date.month - i, 1);
      DateTime endOfMonth =
          DateTime(date.year, date.month - i, lastDay.day, 23, 59, 59, 999);
      Timestamp startTimestamp = Timestamp.fromDate(startOfMonth);
      Timestamp endTimestamp = Timestamp.fromDate(endOfMonth);
      await FirebaseFirestore.instance
          .collection('users/$uid/receipts')
          .where('date', isGreaterThanOrEqualTo: startTimestamp)
          .where('date', isLessThanOrEqualTo: endTimestamp)
          .get()
          .then((doc) {
        double monthTot = 0;
        doc.docs.forEach((element) {
          monthTot += element.data()['total'];
        });
        totals.add(monthTot);
      });
    }
    return totals;
  }

  Future<List<ChartSeries<BarChartModel, String>>> getData() async {
    String currentMonth = getcurrentMonth();
    List<String> months = getOtherMonths();
    months.insert(0, currentMonth);
    months = months.reversed.toList();
    List<double> totals = await getTotalByMonth();
    List<BarChartModel> data = [];
    for (var i = 0; i < 5; i++) {
      var obj = BarChartModel(months[i], totals[i],
          i % 2 == 0 ? const Color(0xff003f9a) : const Color(0xff468fea));
      data.add(obj);
    }
    return <ChartSeries<BarChartModel, String>>[
      ColumnSeries<BarChartModel, String>(
        dataSource: data,
        xValueMapper: (BarChartModel data, _) => data.month,
        yValueMapper: (BarChartModel data, _) => data.total,
        pointColorMapper: (BarChartModel data, _) => data.month == currentMonth
            ? const Color(0xffeaa146)
            : data.barColor,
        animationDuration: 1000,
        borderRadius: const BorderRadius.only(
          topRight: Radius.circular(5),
          topLeft: Radius.circular(5),
        ),
      ),
    ];
  }

这是模型:

class BarChartModel {
  final String month;
  final double total;
  final Color barColor;

  BarChartModel(this.month, this.total, this.barColor);
}

这是我重新加载应用程序时遇到的错误:

type 'Future<List<ChartSeries<BarChartModel, String>>>' is not a subtype of type 'List<ChartSeries<dynamic, dynamic>>'

在这种情况下,摆脱 Future 类型的最佳方法是什么?

4

2 回答 2

1

FutureBuilder 小部件将在这里提供帮助。

查看https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html了解如何使用 FutureBuilder。

基本思路:FutureBuilder 会加载你想要展示的数据。在加载过程中,您将显示一个进度指示器。加载完成后可以显示数据,这将不再是未来,而是实际数据。

于 2022-01-18T11:40:29.407 回答
0

我们从我们这边分析了您的查询,我们建议您使用 FutureBuilder,因为它基于与 Future 交互的最新快照构建自己。我们提供了下面的代码片段供您参考,您可以根据您的要求对其进行修改。

代码片段:

late Future<List<ChartSeries<BarChartModel, String>>> chartData;

 

  @override

  void initState() {

    chartData = getData();

    super.initState();

  }

 

  @override

  Widget build(BuildContext context) {

    return FutureBuilder(

        future: chartData,

        builder: (context, snapshot) {

          if (snapshot.hasData) {

            return SfCartesianChart(

              primaryXAxis: CategoryAxis(

                majorGridLines: const MajorGridLines(width: 0),

                axisLine: const AxisLine(width: 0),

              ),

              primaryYAxis: NumericAxis(

                majorGridLines: const MajorGridLines(width: 0),

                axisLine: const AxisLine(width: 0),

              ),

              plotAreaBorderWidth: 0,

              series: snapshot.data,

            );

          } else if (snapshot.hasError) {

            return const Text('Something went wrong');

          } else {

            return const CircularProgressIndicator();

          }

        });

  }

于 2022-01-24T04:53:38.043 回答