You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中List<dynamic>转List<DataRow>失败及数据加载优化咨询

错误原因分析

出现type 'List<dynamic>' is not a subtype of type 'List<DataRow>'错误的核心原因是类型不匹配:

  • DataTable的rows参数要求传入List<DataRow>类型的数据
  • 你直接将API返回的嵌套lots数组(List<dynamic>或List<Lot>)赋值给了rows,两种类型无法直接转换,导致类型转换异常
解决方法

需要遍历lots数组,将每个Lot对象手动转换为DataRow对象,每个字段对应DataCell。以下是完整示例:

1. 确保模型类正确解析API数据

假设你的API响应结构如下:

{
  "lots": [
    {"id": "L001", "name": "Sample Lot 1", "quantity": 100},
    {"id": "L002", "name": "Sample Lot 2", "quantity": 200}
  ]
}

对应的模型类:

class Lot {
  final String id;
  final String name;
  final int quantity;

  Lot({required this.id, required this.name, required this.quantity});

  factory Lot.fromJson(Map<String, dynamic> json) => Lot(
        id: json['id'],
        name: json['name'],
        quantity: json['quantity'],
      );
}

class ApiResponse {
  final List<Lot> lots;

  ApiResponse({required this.lots});

  factory ApiResponse.fromJson(Map<String, dynamic> json) {
    final List<dynamic> lotsJson = json['lots'];
    return ApiResponse(
      lots: lotsJson.map((lot) => Lot.fromJson(lot)).toList(),
    );
  }
}

2. 在FutureBuilder中正确转换数据

将lots数组转换为List<DataRow>后再赋值给DataTable.rows:

FutureBuilder<ApiResponse>(
  future: fetchLotsData(), // 你的API请求方法
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const CircularProgressIndicator();
    }
    if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    }
    final lots = snapshot.data?.lots ?? [];
    return DataTable(
      columns: const [
        DataColumn(label: Text('ID')),
        DataColumn(label: Text('Lot Name')),
        DataColumn(label: Text('Quantity')),
      ],
      // 核心:将Lot列表转换为DataRow列表
      rows: lots.map((lot) {
        return DataRow(cells: [
          DataCell(Text(lot.id)),
          DataCell(Text(lot.name)),
          DataCell(Text(lot.quantity.toString())),
        ]);
      }).toList(),
    );
  },
)
数据缓存的必要性与实现

是否需要缓存?

如果你的页面会频繁重建(比如屏幕旋转、父组件刷新),建议在initState中缓存数据,避免重复发起网络请求,提升性能并减少资源消耗。如果数据是一次性加载且不会频繁变化,缓存是更优的选择。

实现方式

方式1:缓存API请求的Future(推荐)

将API请求的Future保存在State成员变量中,避免每次build都重新发起请求:

class _LotScreenState extends State<LotScreen> {
  late Future<ApiResponse> _apiRequestFuture;

  @override
  void initState() {
    super.initState();
    // 在initState中发起请求并缓存Future
    _apiRequestFuture = fetchLotsData();
  }

  Future<ApiResponse> fetchLotsData() async {
    final response = await http.get(Uri.parse('your_api_endpoint'));
    if (response.statusCode == 200) {
      return ApiResponse.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load lots data');
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<ApiResponse>(
      future: _apiRequestFuture, // 使用缓存的Future
      builder: (context, snapshot) {
        // 构建UI逻辑...
      },
    );
  }
}

方式2:缓存解析后的List数据

如果需要更灵活地操作数据(比如本地修改、筛选),可以直接缓存解析后的列表:

class _LotScreenState extends State<LotScreen> {
  List<Lot>? _cachedLots;
  bool _isLoading = true;
  String? _errorMsg;

  @override
  void initState() {
    super.initState();
    _loadAndCacheData();
  }

  Future<void> _loadAndCacheData() async {
    try {
      final response = await http.get(Uri.parse('your_api_endpoint'));
      if (response.statusCode == 200) {
        final apiResponse = ApiResponse.fromJson(json.decode(response.body));
        setState(() {
          _cachedLots = apiResponse.lots;
          _isLoading = false;
        });
      } else {
        throw Exception('HTTP error: ${response.statusCode}');
      }
    } catch (e) {
      setState(() {
        _errorMsg = e.toString();
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) return const CircularProgressIndicator();
    if (_errorMsg != null) return Text('Error: $_errorMsg');
    return DataTable(
      columns: const [/* 列定义 */],
      rows: _cachedLots?.map((lot) => DataRow(/* 转换逻辑 */)).toList() ?? [],
    );
  }
}

内容的提问来源于stack exchange,提问作者Najmul.myself

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:10:30