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'], ); } }
错误原因分析
- ListView未被正确返回:当
snapshot.hasData为true时,代码创建了ListView.builder但没有通过return返回,导致逻辑继续执行到最后返回加载指示器,ListView从未被渲染。 - 空值安全隐患:
snapshot.data为可空类型,直接用snapshot.data!.length存在空指针风险;同时Repo层在请求失败或状态码非200时未返回值,会导致Future返回null。 - 布局约束缺失:直接返回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
相关产品推荐
相关产品推荐

