Dart/Flutter中如何修复Series<dynamic, *>类型不匹配错误?
问题现象
在Android Studio中开发Flutter应用、使用charts_flutter包实现图表展示功能时,触发Dart类型不匹配错误:尝试将List<Series<dynamic, dynamic>>类型的值赋值给期望接收List<Series<dynamic, String>>类型的参数时报错。
终端完整错误信息:
Launching lib\main.dart on sdk gphone64 x86 64 in debug mode...
Running Gradle task 'assembleDebug'...
lib/charts_demo.dart:50:7: Error: The argument type 'List<Series<dynamic, dynamic>>' can't be assigned to the parameter type 'List<Series<dynamic, String>>'.
触发场景
将动态定义的seriesList传递给BarChart组件时触发错误,复现代码如下:
import 'package:flutter/material.dart'; import 'package:charts_flutter/flutter.dart' as charts; import 'dart:math'; class ChartsDemo extends StatefulWidget { @override _ChartsDemoState createState() => _ChartsDemoState(); } class _ChartsDemoState extends State<ChartsDemo> { late List<charts.Series<dynamic, String>> seriesList; @override void initState() { super.initState(); seriesList = _createRandomData(); } static List<charts.Series<Sales, String>> _createRandomData() { final random = Random(); return [ charts.Series<Sales, String>( id: "Sales", domainFn: (Sales sales, _) => sales.year, measureFn: (Sales sales, _) => sales.sales, data: List.generate(5, (i) => Sales('${2015 + i}', random.nextInt(100))), ) ]; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Charts Demo")), body: charts.BarChart(seriesList, animate: true), ); } } class Sales { final String year; final int sales; Sales(this.year, this.sales); }
错误原因
Dart泛型默认具备不变性,即List<SubType>不会被自动识别为List<SuperType>的子类型,即使SubType继承自SuperType。
代码中seriesList声明为List<charts.Series<dynamic, String>>类型,但_createRandomData()方法实际返回List<charts.Series<Sales, String>>类型,二者泛型参数不匹配,Dart无法完成隐式类型转换,最终将返回值推导为List<Series<dynamic, dynamic>>触发报错。
解决方案
- 方案1:统一类型声明(推荐)
直接将seriesList的声明类型与数据构造方法的返回类型对齐,使用实际的数据模型类型代替不必要的dynamic声明,无额外运行时开销,类型安全性最高。
仅需要修改seriesList的声明代码:// 原错误声明 // late List<charts.Series<dynamic, String>> seriesList; // 修改为 late List<charts.Series<Sales, String>> seriesList; - 方案2:显式类型转换
如果需要保留dynamic泛型声明以适配多种不同数据结构的图表场景,可以在赋值时调用cast()方法完成显式类型转换:@override void initState() { super.initState(); // 赋值时做显式类型转换 seriesList = _createRandomData().cast<charts.Series<dynamic, String>>(); }
内容的提问来源于stack exchange,提问作者pomoworko.com

