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

Flutter中API数据无法在ListView显示的解决方法咨询

Flutter API数据在ListView中展示的修正方案

你的代码存在几个关键问题导致数据无法正常显示,以下是修正后的完整代码及说明:

修正后的基础版本代码

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

class TeamApiLab extends StatefulWidget {
  @override
  State<TeamApiLab> createState() => _TeamApiLabState();
}

class _TeamApiLabState extends State<TeamApiLab> {
  // 将数据变量移至State类内部,避免全局状态污染,正确初始化空列表
  List<dynamic> listResponse = [];

  Future<void> fetchTeamData() async {
    try {
      final response = await http.get(Uri.parse("https://www.archmage.lk/api/v1/webapi/get-teams"));
      if (response.statusCode == 200) {
        final mapResponse = json.decode(response.body);
        setState(() {
          // 处理API返回data字段为空的情况
          listResponse = mapResponse['data'] ?? [];
        });
      } else {
        setState(() {
          listResponse = [];
          // 加载失败时提示用户
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text("数据加载失败")),
          );
        });
      }
    } catch (e) {
      setState(() {
        listResponse = [];
        // 捕获请求异常并提示
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text("请求异常: $e")),
        );
      });
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: listResponse.length,
      itemBuilder: (context, index) {
        final teamMember = listResponse[index];
        return Container(
          padding: const EdgeInsets.symmetric(vertical: 8),
          child: Column(
            children: [
              CircleAvatar(
                backgroundImage: NetworkImage(teamMember['member_image'] ?? ""),
                // 图片链接为空时显示默认图标
                child: teamMember['member_image'] == null 
                    ? const Icon(Icons.person) 
                    : null,
              ),
              const SizedBox(height: 4),
              // 处理字段为空的情况,避免空指针
              Text(teamMember['name']?.toString() ?? "未知名称"),
              Text(teamMember['status']?.toString() ?? "未知状态"),
            ],
          ),
        );
      },
    );
  }
}

关键修改点说明

  • 变量作用域与初始化:将数据变量从全局移至State类内部,避免全局状态混乱;原代码中List listResponse = {} as List是错误的类型转换,改为正确初始化空列表List<dynamic> listResponse = []。
  • 空安全与异常处理:
    • 使用??运算符处理API返回字段为空的场景,避免空指针异常;
    • 用try-catch包裹网络请求,捕获网络断开等异常;
    • 状态码非200时清空数据并提示错误。
  • 命名规范修正:类名改为大驼峰格式(TeamApiLab、_TeamApiLabState),符合Dart语言规范。
  • UI健壮性优化:添加间距、图片加载失败的兜底图标,提升用户体验。

进阶优化:用FutureBuilder管理异步状态

如果需要更优雅地处理加载中、错误、无数据等状态,推荐使用FutureBuilder替代initState+setState的方式:

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

class TeamApiLab extends StatefulWidget {
  @override
  State<TeamApiLab> createState() => _TeamApiLabState();
}

class _TeamApiLabState extends State<TeamApiLab> {
  Future<List<dynamic>> fetchTeamData() async {
    final response = await http.get(Uri.parse("https://www.archmage.lk/api/v1/webapi/get-teams"));
    if (response.statusCode == 200) {
      final mapResponse = json.decode(response.body);
      return mapResponse['data'] ?? [];
    } else {
      throw Exception("数据加载失败");
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<dynamic>>(
      future: fetchTeamData(),
      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!.isEmpty) {
          // 无数据状态提示
          return const Center(child: Text("暂无团队数据"));
        } else {
          // 数据加载完成渲染列表
          return ListView.builder(
            itemCount: snapshot.data!.length,
            itemBuilder: (context, index) {
              final teamMember = snapshot.data![index];
              return Container(
                padding: const EdgeInsets.symmetric(vertical: 8),
                child: Column(
                  children: [
                    CircleAvatar(
                      backgroundImage: NetworkImage(teamMember['member_image'] ?? ""),
                      child: teamMember['member_image'] == null 
                          ? const Icon(Icons.person) 
                          : null,
                    ),
                    const SizedBox(height: 4),
                    Text(teamMember['name']?.toString() ?? "未知名称"),
                    Text(teamMember['status']?.toString() ?? "未知状态"),
                  ],
                ),
              );
            },
          );
        }
      },
    );
  }
}

这个版本通过FutureBuilder自动管理异步请求的全生命周期状态,代码更简洁,状态逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 15:12:49