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

Flutter API分类数据获取失败:加载指示器持续运行无数据

问题分析与解决方案

你的代码存在几个关键问题,导致加载指示器持续运行且无法展示数据,以下是具体问题和修复步骤:

1. 数据模型与API解析不匹配

你的API返回结构应该是外层包含data数组的对象(比如{"data": [{"id":1,...},...]}),但你在fetchCategory里直接把整个响应当成数组遍历,同时错误地将categories定义为List<Category>,而实际需要的是List<Datum>(每个分类项是Datum实例)。另外Category类里的category_name getter完全无用,还会导致UI调用错误。

2. FutureBuilder重复发起请求

每次Widget build时都会调用fetchCategory(),导致重复发起API请求,同时你依赖state里的categories而不是FutureBuilder的snapshot数据,逻辑混乱。


修复步骤

步骤1:修正数据模型(Category.dart)

删除Category类中无用的category_name getter,模型保持其余部分不变:

import 'dart:convert';

Category categoryFromJson(String str) => Category.fromJson(json.decode(str));

String categoryToJson(Category data) => json.encode(data.toJson());

class Category {
    List<Datum> data;

    Category({
        required this.data,
    });

    factory Category.fromJson(Map<String, dynamic> json) => Category(
        data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "data": List<dynamic>.from(data.map((x) => x.toJson())),
    };
}

class Datum {
    int id;
    String image;
    String categoryName;
    String categoryDes;
    int activation;
    DateTime createdAt;
    DateTime updatedAt;

    Datum({
        required this.id,
        required this.image,
        required this.categoryName,
        required this.categoryDes,
        required this.activation,
        required this.createdAt,
        required this.updatedAt,
    });

    factory Datum.fromJson(Map<String, dynamic> json) => Datum(
        id: json["id"],
        image: json["image"],
        categoryName: json["category_name"],
        categoryDes: json["category_des"],
        activation: json["activation"],
        createdAt: DateTime.parse(json["created_at"]),
        updatedAt: DateTime.parse(json["updated_at"]),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "image": image,
        "category_name": categoryName,
        "category_des": categoryDes,
        "activation": activation,
        "created_at": createdAt.toIso8601String(),
        "updated_at": updatedAt.toIso8601String(),
    };
}

步骤2:修正CategorySlider逻辑

修改状态变量类型、API解析逻辑、FutureBuilder使用方式:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../models/Category.dart';

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

  @override
  State<CategorySlider> createState() => _CategorySliderState();
}

class _CategorySliderState extends State<CategorySlider> {
  List<Datum> categories = [];
  late Future<List<Datum>> _fetchCategoriesFuture; // 存储Future避免重复请求

  @override
  void initState() {
    super.initState();
    _fetchCategoriesFuture = fetchCategory(); // 在initState里初始化请求
  }

  Future<List<Datum>> fetchCategory() async {
    final response = await http.get(Uri.parse('http://127.0.0.1:8000/api/category'));

    if (response.statusCode == 200) {
      // 正确解析API响应:先转成Category对象,再取data列表
      Category categoryResponse = Category.fromJson(jsonDecode(response.body));
      setState(() {
        categories = categoryResponse.data;
      });
      return categoryResponse.data;
    } else {
      throw Exception('Failed to load categories'); // 抛出错误便于snapshot捕获
    }
  }  
  
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Datum>>(
        future: _fetchCategoriesFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('加载失败: ${snapshot.error}')); // 显示错误信息
          } else if (snapshot.hasData && snapshot.data!.isNotEmpty) {
            return ListView.builder(
              scrollDirection: Axis.horizontal,
              shrinkWrap: true,
              padding: const EdgeInsets.only(right: 8),
              itemCount: snapshot.data!.length,
              itemBuilder: (BuildContext context, int index) {
                final category = snapshot.data![index];
                return Container(
                  child: Center(
                    child: Column(
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.all(10.0),
                          child: SizedBox(
                            width: 200,
                            height: 120,
                            child: ElevatedButton(
                              style: ElevatedButton.styleFrom(
                                  backgroundColor: Colors.white,
                                  shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.circular(20),
                                      side: const BorderSide(color: Color(0xFF1818B4)))),
                              onPressed: () {},
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                crossAxisAlignment: CrossAxisAlignment.center,
                                children: <Widget>[
                                  Text(category.categoryName), // 使用正确的属性名
                                ],
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                );
              },
            );
          } else {
            return const Center(child: Text('暂无分类数据'));
          }
        });
  }
}

关键修复点说明

  • 将categories类型改为List<Datum>,对应API返回的每个分类项。
  • 使用late Future<List<Datum>>存储请求Future,避免每次build重复发起API请求。
  • 正确解析API响应:先将整个响应转为Category对象,再提取内部的data数组。
  • 在FutureBuilder中基于snapshot.data构建UI,同时处理加载中、错误、空数据等状态。
  • 移除UI中错误的category_name调用,改用Datum类的categoryName属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:07:34