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

Flutter中如何从REST API获取数据并在ListView中展示

Flutter中从REST API获取数据并展示在ListView的解决方案

核心修改点

  • 调整API数据解析逻辑,适配数组类型的返回结果
  • 使用FutureBuilder处理异步请求的状态(加载、错误、成功)
  • 解决Column嵌套ListView的布局溢出问题

修改后的完整代码

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

class TransactionDetails {
  final String avatar;
  final String name;
  final String date;
  final String amount;

  TransactionDetails({
    required this.avatar,
    required this.name,
    required this.date,
    required this.amount,
  });

  // 从单个JSON对象创建实例
  factory TransactionDetails.fromJson(Map<String, dynamic> json) {
    return TransactionDetails(
      avatar: json['avatar'],
      name: json['name'],
      date: json['date'],
      amount: json['amount'],
    );
  }

  // 从JSON数组转换为List<TransactionDetails>
  static List<TransactionDetails> fromJsonList(List<dynamic> jsonList) {
    return jsonList.map((json) => TransactionDetails.fromJson(json)).toList();
  }
}

class BaseScreen extends StatelessWidget {
  const BaseScreen({Key? key}) : super(key: key);

  // 修改为返回列表类型的Future
  Future<List<TransactionDetails>> fetchTransactions() async {
    final response = await http.get(
      Uri.parse('https://brotherlike-navies.000webhostapp.com/people/people.php'),
    );

    if (response.statusCode == 200) {
      final List<dynamic> jsonData = json.decode(response.body);
      return TransactionDetails.fromJsonList(jsonData);
    } else {
      throw Exception('请求失败,请检查网络或API地址');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SizedBox(
              width: double.infinity,
              height: 150,
              child: ListView(
                scrollDirection: Axis.horizontal,
                children: [
                  Container(
                    margin: const EdgeInsets.all(15),
                    width: 319,
                    height: 100,
                    color: Colors.green,
                    alignment: Alignment.center,
                    child: const Text(
                      '\$5200.00',
                      style: TextStyle(
                        fontSize: 15,
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                  Container(
                    margin: const EdgeInsets.all(15),
                    width: 319,
                    height: 100,
                    color: Colors.green,
                    alignment: Alignment.center,
                    child: const Text(
                      '\$1200.00',
                      style: TextStyle(
                        fontSize: 15,
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ],
              ),
            ),
            const Padding(
              padding: EdgeInsets.all(15),
              child: Text(
                "Recent Transactions",
                style: TextStyle(
                  fontSize: 14,
                  fontWeight: FontWeight.bold,
                  color: Colors.green,
                ),
              ),
            ),
            // 用Expanded包裹ListView,解决Column布局溢出问题
            Expanded(
              child: FutureBuilder<List<TransactionDetails>>(
                future: fetchTransactions(),
                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(
                      itemCount: snapshot.data!.length,
                      itemBuilder: (context, index) {
                        final transaction = snapshot.data![index];
                        return ListTile(
                          leading: CircleAvatar(
                            backgroundImage: NetworkImage(transaction.avatar),
                          ),
                          title: Text(transaction.name),
                          subtitle: Text(transaction.date),
                          trailing: Text(
                            '\$${transaction.amount}',
                            style: const TextStyle(
                              fontWeight: FontWeight.bold,
                              color: Colors.green,
                            ),
                          ),
                        );
                      },
                    );
                  }
                  // 空数据状态
                  else {
                    return const Center(child: Text('暂无交易记录'));
                  }
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

关键说明

  1. 数据解析调整:新增fromJsonList静态方法,将API返回的JSON数组转换为List<TransactionDetails>,同时修改fetchTransactions方法返回列表类型的Future。
  2. FutureBuilder的使用:通过FutureBuilder监听异步请求的状态,分别处理加载中、错误、成功、空数据四种场景,确保UI状态和数据状态同步。
  3. 布局问题解决:用Expanded包裹ListView,让它在Column中占据剩余空间,避免布局溢出;同时使用ListView.builder实现懒加载,提升列表性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:35:36