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

Flutter加载本地JSON资产报错,ListView无法展示数据求助

解决Flutter加载JSON资产并展示ListView的问题

一、修复资产加载错误

错误提示Unable to load asset,核心原因是资产未正确配置或路径错误:

  1. 检查pubspec.yaml的资产声明
    确保在flutter节点下正确添加JSON文件路径,注意缩进必须为2个空格:

    flutter:
      assets:
        - lib/data/json/foods/foods.json
    

    配置完成后执行flutter pub get刷新资产列表。

  2. 修正资产路径
    Flutter资产路径从项目根目录开始,无需额外前缀。若文件实际放在项目根目录的assets文件夹下,需同步修改路径为assets/data/json/foods/foods.json并更新pubspec配置。

二、修复JSON文件格式

你提供的JSON片段是多个独立对象,缺少外层数组包裹,会导致json.decode后得到单个Map而非List,遍历过程报错。修改JSON为数组格式:

[
    {
        "name": "Chobani Greek Yogurt",
        "caloriesPer100g": 59,
        "fatPer100g": 0,
        "ofWhichSaturates": 0,
        "carbohydratesPer100g": 4,
        "ofWhichSugars": 4,
        "proteinPer100g": 10,
        "SodiumPer100g": 0.04,
        "ServingSizeGrams": 150 
    },
    {
        "name": "Oikos Triple Zero Greek Yogurt",
        "caloriesPer100g": 83,
        "fatPer100g": 0,
        "ofWhichSaturates": 0,
        "carbohydratesPer100g": 6,
        "ofWhichSugars": 6,
        "proteinPer100g": 15,
        "SodiumPer100g": 0.06,
        "ServingSizeGrams": 150 
    },
    {
        "name": "Fage Total 0% Greek Yogurt",
        "caloriesPer100g": 50,
        "fatPer100g": 0,
        "ofWhichSaturates": 0,
        "carbohydratesPer100g": 4,
        "ofWhichSugars": 4,
        "proteinPer100g": 10,
        "SodiumPer100g": 0.05,
        "ServingSizeGrams": 150 
    }
]

三、优化页面代码逻辑

页面存在重复加载数据、context使用不当等问题,修改后的代码如下:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sg_training/data/json/foods/foods.dart';

class AddFood extends StatefulWidget {
  @override
  _AddFoodState createState() => _AddFoodState();
}

class _AddFoodState extends State<AddFood> {
  List<Food> _foods = [];
  bool _isLoading = true;

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

  Future<void> fetchFoods() async {
    try {
      String jsonString = await rootBundle.loadString('lib/data/json/foods/foods.json');
      List<dynamic> foodsJson = json.decode(jsonString);

      List<Food> foods = [];
      for (var foodJson in foodsJson) {
        foods.add(Food.fromJson(foodJson));
      }

      setState(() {
        _foods = foods;
        _isLoading = false;
      });
    } catch (e) {
      print('加载或解析错误: $e');
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        leading: BackButton(
          onPressed: () => Navigator.pop(context),
        ),
        title: const Text("SG training"),
        backgroundColor: Colors.blueGrey,
      ),
      body: _isLoading 
          ? const Center(child: CircularProgressIndicator())
          : ListView.builder(
              itemBuilder: (context, index) {
                return Card(
                  child: Padding(
                    padding: const EdgeInsets.all(15),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          _foods[index].name ?? '未知食品',
                          style: const TextStyle(
                              fontSize: 15.0, fontWeight: FontWeight.bold),
                        ),
                        Text(
                          _foods[index].caloriesPer100g.toString(),
                          style: TextStyle(color: Colors.grey.shade700),
                        )
                      ],
                    ),
                  ),
                );
              },
              itemCount: _foods.length,
            ),
    );
  }
}

四、优化Food解析类

给name字段添加空值默认,避免JSON中缺少name导致崩溃:

class Food {
  String name;
  double caloriesPer100g;
  double fatPer100g;
  double ofWhichSaturates;
  double carbohydratesPer100g;
  double ofWhichSugars;
  double proteinPer100g;
  double SodiumPer100g;
  double ServingSizeGrams;

  Food(
    this.name,
    this.caloriesPer100g,
    this.fatPer100g,
    this.ofWhichSaturates,
    this.carbohydratesPer100g,
    this.ofWhichSugars,
    this.proteinPer100g,
    this.SodiumPer100g,
    this.ServingSizeGrams,
  );

  Food.fromJson(Map<String, dynamic> json)
      : name = json['name'] ?? '未知食品',
        caloriesPer100g = json["caloriesPer100g"] ?? 0.0,
        fatPer100g = json["fatPer100g"] ?? 0.0,
        ofWhichSaturates = json["ofWhichSaturates"] ?? 0.0,
        carbohydratesPer100g = json["carbohydratesPer100g"] ?? 0.0,
        ofWhichSugars = json["ofWhichSugars"] ?? 0.0,
        proteinPer100g = json["proteinPer100g"] ?? 0.0,
        SodiumPer100g = json["SodiumPer100g"] ?? 0.0,
        ServingSizeGrams = json["ServingSizeGrams"] ?? 0.0;
}

按以上步骤逐一排查修改,即可解决加载错误和列表展示问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 06:00:13