Flutter加载本地JSON资产报错,ListView无法展示数据求助
解决Flutter加载JSON资产并展示ListView的问题
一、修复资产加载错误
错误提示Unable to load asset,核心原因是资产未正确配置或路径错误:
检查pubspec.yaml的资产声明
确保在flutter节点下正确添加JSON文件路径,注意缩进必须为2个空格:flutter: assets: - lib/data/json/foods/foods.json配置完成后执行
flutter pub get刷新资产列表。修正资产路径
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
相关产品推荐
相关产品推荐

