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

Flutter中FutureBuilder无法展示JSON数据问题求助

问题:FutureBuilder获取数据后,ListView检查长度失败

我尝试通过FutureBuilder拉取https://jsonplaceholder.typicode.com/posts的JSON数据,并用ListView展示,但发现FutureBuilder已获取数据,ListView在检查长度时却失败了。以下是我的代码:


Main 文件

import 'package:flutter/material.dart';
import 'package:fresh_project/screens/homepage.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const Homepage(),
    );
  }
}

Homepage(数据加载页面)

import 'package:flutter/material.dart';
import 'package:fresh_project/models/user.dart';
import 'package:fresh_project/network/users_repo.dart';

class Homepage extends StatefulWidget {
  const Homepage({Key? key}) : super(key: key);

  @override
  State<Homepage> createState() => _HomepageState();
}

class _HomepageState extends State<Homepage> {
  late Future<List<User>?>? listOfUsers;
  final UsersRepo _userRepo = UsersRepo();

  @override
  void initState() {
    super.initState();
    listOfUsers = _userRepo.fetchUsers();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<User>?>(
      future: listOfUsers,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          ListView.builder(
            itemCount: snapshot.data!.length,
            itemBuilder: (context, index) {
              return Padding(
                padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 4),
                child: Text(
                  snapshot.data![index].title!,
                ),
              );
            },
          );
        } else if (snapshot.hasError) {
          print('Failed to load users');
        }
        return const Center(
          child: SizedBox(
            width: 200,
            height: 200,
            child: CircularProgressIndicator(),
          ),
        );
      },
    );
  }
}

Repo 文件

import 'dart:convert';

import 'package:fresh_project/constants/api_constants.dart';
import 'package:http/http.dart' as http;
import 'package:fresh_project/models/user.dart';

class UsersRepo{
  Future<List<User>?> fetchUsers() async {
    try{
      final response = await http.get(Uri.parse(ApiConstants.url + ApiConstants.endpoint));
      if(response.statusCode == 200){
        return returnUsers(response.body);
      }
    } catch(e){
      // ignore: avoid_print
      print(e.toString());
    }
  }
}

List<User> returnUsers(String json){
  List<User> tempList = [];
  var decodedJson = jsonDecode(json);
  for(var instance in decodedJson){
    tempList.add(User.fromJson(instance));
  }
  return tempList;
}

Model 文件

class User {
  final int? userId;
  final int? id;
  final String? title;
  final String? body;

  User(this.userId, this.id, this.title, this.body);

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      json['userId'],
      json['id'],
      json['title'],
      json['body'],
    );
  }
}

错误原因分析

  1. ListView未被正确返回:当snapshot.hasData为true时,代码创建了ListView.builder但没有通过return返回,导致逻辑继续执行到最后返回加载指示器,ListView从未被渲染。
  2. 空值安全隐患:snapshot.data为可空类型,直接用snapshot.data!.length存在空指针风险;同时Repo层在请求失败或状态码非200时未返回值,会导致Future返回null。
  3. 布局约束缺失:直接返回ListView没有外层容器(如Scaffold),会因缺少布局约束引发渲染错误。

修正后的代码

1. Homepage 页面

import 'package:flutter/material.dart';
import 'package:fresh_project/models/user.dart';
import 'package:fresh_project/network/users_repo.dart';

class Homepage extends StatefulWidget {
  const Homepage({Key? key}) : super(key: key);

  @override
  State<Homepage> createState() => _HomepageState();
}

class _HomepageState extends State<Homepage> {
  late Future<List<User>?> listOfUsers;
  final UsersRepo _userRepo = UsersRepo();

  @override
  void initState() {
    super.initState();
    listOfUsers = _userRepo.fetchUsers();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<List<User>?>(
        future: listOfUsers,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(
              child: SizedBox(
                width: 200,
                height: 200,
                child: CircularProgressIndicator(),
              ),
            );
          } else if (snapshot.hasError) {
            return const Center(child: Text('加载用户失败'));
          } else if (snapshot.hasData && snapshot.data != null) {
            final users = snapshot.data!;
            return ListView.builder(
              itemCount: users.length,
              itemBuilder: (context, index) {
                return Padding(
                  padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 4),
                  child: Text(users[index].title ?? '无标题'),
                );
              },
            );
          } else {
            return const Center(child: Text('暂无数据'));
          }
        },
      ),
    );
  }
}

2. UsersRepo 层

import 'dart:convert';

import 'package:fresh_project/constants/api_constants.dart';
import 'package:http/http.dart' as http;
import 'package:fresh_project/models/user.dart';

class UsersRepo{
  Future<List<User>?> fetchUsers() async {
    try{
      final response = await http.get(Uri.parse(ApiConstants.url + ApiConstants.endpoint));
      if(response.statusCode == 200){
        return returnUsers(response.body);
      } else {
        return [];
      }
    } catch(e){
      print(e.toString());
      return [];
    }
  }
}

List<User> returnUsers(String json){
  List<User> tempList = [];
  var decodedJson = jsonDecode(json);
  for(var instance in decodedJson){
    tempList.add(User.fromJson(instance));
  }
  return tempList;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:50:39