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

Flutter如何展示Node.js服务端返回的MySQL查询结果列表

错误原因

你的解析逻辑预期接收根结构为Map<String, dynamic>的JSON对象,但Node.js服务端返回的MySQL查询结果是根结构为List<dynamic>的JSON数组,类型不匹配导致抛出cast异常。

代码重构步骤

1. 修正数据请求与实体解析逻辑

原有请求方法大概率是直接将返回结果传入Subject.fromJson,需要调整为遍历JSON数组的每一项,逐个转换为Subject实体,最终返回List<Subject>类型:

import 'dart:convert';
import 'package:http/http.dart' as http;

// 修正后的请求方法,返回科目列表
Future<List<Subject>> fetchSubjectList() async {
  final response = await http.get(Uri.parse('替换为你的后端接口地址'));
  if (response.statusCode == 200) {
    // 先将返回内容解析为List类型
    final List<dynamic> jsonArray = jsonDecode(response.body);
    // 遍历数组每一项转换为Subject实体
    return jsonArray.map((item) => Subject.fromJson(item)).toList();
  } else {
    throw Exception('请求接口失败,状态码:${response.statusCode}');
  }
}

2. 调整FutureBuilder渲染逻辑

根据你的展示需求,可选择列表或表格两种实现方式:

列表展示实现

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('科目列表')),
    body: FutureBuilder<List<Subject>>(
      future: fetchSubjectList(),
      builder: (context, snapshot) {
        // 加载中状态
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        }
        // 加载出错状态
        if (snapshot.hasError) {
          return Center(child: Text('加载失败:${snapshot.error}'));
        }
        // 加载成功状态
        if (snapshot.hasData) {
          final subjectList = snapshot.data!;
          return ListView.builder(
            itemCount: subjectList.length,
            itemBuilder: (context, index) {
              final subject = subjectList[index];
              return ListTile(
                title: Text(subject.title), // 替换为你的Subject实体对应字段
                subtitle: Text('科目ID:${subject.id}'), // 可自定义添加更多字段展示
              );
            },
          );
        }
        // 无数据状态
        return const Center(child: Text('暂无科目数据'));
      },
    ),
  );
}

表格展示实现

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('科目表格')),
    body: FutureBuilder<List<Subject>>(
      future: fetchSubjectList(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        }
        if (snapshot.hasError) {
          return Center(child: Text('加载失败:${snapshot.error}'));
        }
        if (snapshot.hasData) {
          final subjectList = snapshot.data!;
          return SingleChildScrollView(
            // 横向滚动适配多列表格
            scrollDirection: Axis.horizontal,
            child: DataTable(
              columns: const [
                DataColumn(label: Text('科目ID')),
                DataColumn(label: Text('科目标题')),
                DataColumn(label: Text('学分')),
                DataColumn(label: Text('课时')),
              ],
              rows: subjectList.map((subject) {
                return DataRow(cells: [
                  DataCell(Text(subject.id.toString())),
                  DataCell(Text(subject.title)),
                  DataCell(Text(subject.credit.toString())),
                  DataCell(Text(subject.classHour.toString())),
                ]);
              }).toList(),
            ),
          );
        }
        return const Center(child: Text('暂无科目数据'));
      },
    ),
  );
}
注意事项
  • 确保Subject.fromJson方法的入参为Map<String, dynamic>类型,且字段映射和后端返回的单条科目结构完全匹配
  • 若后端可能返回空数组,可添加长度判断做自定义空态展示

内容的提问来源于stack exchange,提问作者Irwin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:48:03