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

Flutter调用USDA API展示食物营养详情时出现空值问题求助

问题排查与解决方案

1. 确认页面传参正确性

点击列表项跳转至DetailScreen时,必须确保传递了正确的食物标识(如ID):

  • 跳转代码示例:
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => DetailScreen(foodId: food.id), // 此处需传入正确的食物ID
  ),
);
  • DetailScreen构造函数需正确接收参数:
class DetailScreen extends StatelessWidget {
  final String foodId;
  const DetailScreen({super.key, required this.foodId});
  // ...
}

2. 校验API请求逻辑

检查DetailScreen中获取营养数据的API调用:

  • 确认请求URL使用了正确的参数:
final response = await http.get(Uri.parse('https://你的API地址/nutrition/${widget.foodId}'));
  • 仅在响应状态码为200时解析数据:
if (response.statusCode == 200) {
  final data = jsonDecode(response.body);
  final foodNutrition = FoodModel.fromJson(data);
} else {
  // 处理请求失败场景,比如展示错误提示
}

3. 修正Food Model的JSON解析

确保fromJson方法与API返回的字段完全匹配,避免因字段名不符导致数据为null:

class FoodModel {
  final String? name;
  final Nutrition? nutrition;

  FoodModel({this.name, this.nutrition});

  factory FoodModel.fromJson(Map<String, dynamic> json) {
    return FoodModel(
      name: json['food_name'], // 需与API返回的字段名一致
      nutrition: json['nutrition'] != null ? Nutrition.fromJson(json['nutrition']) : null,
    );
  }
}

class Nutrition {
  final double? calories;
  final double? protein;

  Nutrition({this.calories, this.protein});

  factory Nutrition.fromJson(Map<String, dynamic> json) {
    return Nutrition(
      calories: json['calories']?.toDouble(), // 处理类型转换,避免int转double报错
      protein: json['protein']?.toDouble(),
    );
  }
}
  • 对可能为null的字段添加空判断,防止解析时抛出异常。

4. 完善页面状态处理

在DetailScreen中处理加载中、加载成功、加载失败三种状态,避免直接展示null数据:

class DetailScreen extends StatefulWidget {
  final String foodId;
  const DetailScreen({super.key, required this.foodId});

  @override
  State<DetailScreen> createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  FoodModel? _food;
  bool _isLoading = true;
  String? _error;

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

  Future<void> _fetchNutritionData() async {
    try {
      final response = await http.get(Uri.parse('https://你的API地址/nutrition/${widget.foodId}'));
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        setState(() {
          _food = FoodModel.fromJson(data);
          _isLoading = false;
        });
      } else {
        setState(() {
          _error = '请求失败,状态码:${response.statusCode}';
          _isLoading = false;
        });
      }
    } catch (e) {
      setState(() {
        _error = '加载出错:$e';
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('营养详情')),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : _error != null
              ? Center(child: Text(_error!))
              : _food == null
                  ? const Center(child: Text('未找到营养数据'))
                  : Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text('食物名称:${_food!.name ?? '未知'}', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                          const SizedBox(height: 16),
                          Text('热量:${_food!.nutrition?.calories ?? 0} kcal'),
                          Text('蛋白质:${_food!.nutrition?.protein ?? 0} g'),
                          // 其他营养字段展示
                        ],
                      ),
                    ),
    );
  }
}
  • 使用空合并运算符??,当数据为null时展示默认值(如0或“未知”),避免界面空白。

5. 实用调试技巧

  • 打印API返回的原始JSON数据,确认字段与Model定义是否一致:
print('API返回数据:${response.body}');
  • 检查网络权限:
    • Android:在AndroidManifest.xml中添加<uses-permission android:name="android.permission.INTERNET" />
    • iOS:在Info.plist中配置NSAppTransportSecurity允许HTTP请求(若API为HTTP协议)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:12:09