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

Flutter空安全下解析JSON生成可编辑数据表遇List构造器不可用错误

问题修复与功能实现方案

1 报错原因与data.dart修复

你遇到的构造器报错是Dart 2.12+空安全版本后,官方移除了默认的List()构造器导致的。同时原有代码还存在两处逻辑问题:

  • List<Results>初始化写法错误,参数传递无效
  • 实体类字段和你提供的JSON结构不匹配,JSON根节点下是skills数组,不存在previous/next/results字段

修复后的完整data.dart代码:

class Data {
  late List<Results> skills;

  Data.fromJson(Map<String, dynamic> json) {
    skills = []; // 直接用列表字面量初始化空列表,兼容空安全
    if (json['skills'] != null) {
      json['skills'].forEach((v) {
        skills.add(Results.fromJson(v));
      });
    }
  }
}

class Results {
  // 从JSON读取的固定字段
  String skills = " ";
  String testLink = "";
  // 新增可编辑字段
  int months = 0;
  double selfScore = 0.0;
  double testScore = 0.0;
  String comments = "";

  Results.fromJson(Map<String, dynamic> json) {
    skills = json['skills'] ?? "";
    testLink = json['test'] ?? "";
  }
}

2 依赖配置与JSON修正

首先修正你提供的样例JSON语法错误(缺少数组闭合符):

{
  "skills": [
    {
      "skills": "C#",
      "test": "//www.google.com/"
    },
    {
      "skills": ".Net Core",
      "test": "//www.google.com/"
    },
    {
      "skills": "ASP.Net",
      "test": "//www.google.com/"
    }
  ]
}

然后需要在pubspec.yaml中声明本地JSON资源路径,否则无法读取文件:

flutter:
  assets:
    - lib/data.json

3 DataProvider功能增强

优化原有数据读取逻辑,新增可编辑字段更新方法:

import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'data.dart';

class MyDataProvider extends ChangeNotifier {
  Data? d;
  bool isLoading = false;

  Future getData(BuildContext context) async {
    isLoading = true;
    notifyListeners();
    var response = await DefaultAssetBundle.of(context)
        .loadString('lib/data.json');
    var mJson = json.decode(response);
    d = Data.fromJson(mJson);
    isLoading = false;
    notifyListeners();
  }

  // 可编辑字段更新方法
  void updateField(int index, {
    int? months,
    double? selfScore,
    double? testScore,
    String? comments,
  }) {
    if (d == null || index >= d!.skills.length) return;
    if (months != null) d!.skills[index].months = months;
    if (selfScore != null) d!.skills[index].selfScore = selfScore;
    if (testScore != null) d!.skills[index].testScore = testScore;
    if (comments != null) d!.skills[index].comments = comments;
    notifyListeners();
  }
}

4 可编辑数据表Widget实现

使用官方DataTable组件实现需求,可编辑字段点击后弹出输入框修改:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'dataprovider.dart';

class SkillTablePage extends StatefulWidget {
  const SkillTablePage({super.key});

  @override
  State<SkillTablePage> createState() => _SkillTablePageState();
}

class _SkillTablePageState extends State<SkillTablePage> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      Provider.of<MyDataProvider>(context, listen: false).getData(context);
    });
  }

  // 编辑弹窗逻辑
  void showEditDialog(int index, String field, dynamic currentValue) {
    final controller = TextEditingController(text: currentValue.toString());
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('编辑$field'),
        content: TextField(
          controller: controller,
          keyboardType: field == '使用时长(月)' ? TextInputType.number :
          field.contains('分数') ? const TextInputType.numberWithOptions(decimal: true) :
          TextInputType.text,
        ),
        actions: [
          TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
          TextButton(
            onPressed: () {
              final provider = Provider.of<MyDataProvider>(context, listen: false);
              switch(field) {
                case '使用时长(月)':
                  provider.updateField(index, months: int.tryParse(controller.text) ?? 0);
                  break;
                case '自评分数':
                  provider.updateField(index, selfScore: double.tryParse(controller.text) ?? 0.0);
                  break;
                case '考试分数':
                  provider.updateField(index, testScore: double.tryParse(controller.text) ?? 0.0);
                  break;
                case '备注':
                  provider.updateField(index, comments: controller.text);
                  break;
              }
              Navigator.pop(context);
            },
            child: const Text('确认'),
          )
        ],
      )
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('技能数据表')),
      body: Consumer<MyDataProvider>(
        builder: (context, provider, child) {
          if (provider.isLoading) {
            return const Center(child: CircularProgressIndicator());
          }
          if (provider.d == null) {
            return const Center(child: Text('暂无数据'));
          }
          return SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: DataTable(
              columns: const [
                DataColumn(label: Text('skills')),
                DataColumn(label: Text('months')),
                DataColumn(label: Text('selfscore')),
                DataColumn(label: Text('testscore')),
                DataColumn(label: Text('testlink')),
                DataColumn(label: Text('comments')),
              ],
              rows: provider.d!.skills.asMap().entries.map((entry) {
                int index = entry.key;
                Results item = entry.value;
                return DataRow(cells: [
                  DataCell(Text(item.skills)),
                  DataCell(Text(item.months.toString()), onTap: () => showEditDialog(index, '使用时长(月)', item.months)),
                  DataCell(Text(item.selfScore.toStringAsFixed(1)), onTap: () => showEditDialog(index, '自评分数', item.selfScore)),
                  DataCell(Text(item.testScore.toStringAsFixed(1)), onTap: () => showEditDialog(index, '考试分数', item.testScore)),
                  DataCell(Text(item.testLink)),
                  DataCell(Text(item.comments.isEmpty ? '点击填写' : item.comments), onTap: () => showEditDialog(index, '备注', item.comments)),
                ]);
              }).toList(),
            ),
          );
        },
      ),
    );
  }
}

最后在项目入口注册Provider即可正常使用该页面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:06:08