Flutter调用Get API转对象列表返回空列表问题排查
问题
通过Get API获取数据并转换为列表,尝试创建Post模型并将该列表转为Post对象列表,但实际返回空列表,求原因。
API返回的JSON数据:
[ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" } ]
PostModel代码:
class Post { int? userId; int? id; String? title; String? body; Post({ this.userId, this.id, this.title, this.body, }); factory Post.fromJson(List json, int index) { return Post( userId: json[index]['userId'], id: json[index]['id'], title: json[index]['title'], body: json[index]['body'], ); } }
PostService及HomeScreen代码:
import 'dart:convert'; import '../models/post_model.dart'; import 'package:http/http.dart' as http; class PostService { final url = Uri.parse('https://jsonplaceholder.typicode.com/posts'); Future<List<Post?>?> callPost() async { var response = await http.get(url); if (response.statusCode == 200) { List myList = jsonDecode(response.body); List<Post> _allPosts = List.generate(myList.length, (index) => Post.fromJson(myList, index)); return _allPosts; } else { print('error code: ${response.statusCode}'); } } } class HomeScreen extends StatefulWidget { HomeScreen({Key? key}) : super(key: key); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { PostService _postService = PostService(); List<Post?> myPostList = []; @override void initState() { _personelService.callPost().then((value) { if (value != null) { setState(() { myPostList = value; }); } else { setState(() {}); } }); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: SingleChildScrollView( child: Column( children: [ Text('${myPostList[0]!.body}'), ], ), ), ), ); } }
期望得到Post对象列表,但实际返回空列表,求解释原因。
问题原因及修复方案
核心原因1:变量名错误
在_HomeScreenState的initState方法中,调用的是_personelService.callPost(),但你定义的服务实例是_postService,变量名不匹配,导致实际根本没有发起API请求,myPostList始终是空列表。
核心原因2:Post.fromJson设计不合理
当前Post.fromJson接收整个列表和索引来创建对象,不符合常规JSON解析逻辑,常规应该接收单个JSON对象(即列表中的每个元素)来创建Post实例,代码冗余且易出错。
额外隐患:空列表直接访问下标会崩溃
在build方法中直接写myPostList[0]!.body,如果myPostList为空(请求未完成或失败时),会直接抛出下标越界异常,需要先做空判断。
修复后的代码
1. 修正PostModel的fromJson方法
class Post { int? userId; int? id; String? title; String? body; Post({ this.userId, this.id, this.title, this.body, }); // 改为接收单个JSON对象 factory Post.fromJson(Map<String, dynamic> json) { return Post( userId: json['userId'], id: json['id'], title: json['title'], body: json['body'], ); } }
2. 优化PostService的列表转换逻辑
class PostService { final url = Uri.parse('https://jsonplaceholder.typicode.com/posts'); Future<List<Post>> callPost() async { var response = await http.get(url); if (response.statusCode == 200) { List<dynamic> myList = jsonDecode(response.body); // 使用map遍历每个JSON对象转换为Post return myList.map((json) => Post.fromJson(json)).toList(); } else { throw Exception('请求失败,状态码:${response.statusCode}'); } } }
3. 修正HomeScreen的变量名并增加状态判断
class _HomeScreenState extends State<HomeScreen> { PostService _postService = PostService(); List<Post> myPostList = []; bool isLoading = true; // 增加加载状态标识 @override void initState() { super.initState(); _fetchPosts(); } Future<void> _fetchPosts() async { try { List<Post> posts = await _postService.callPost(); setState(() { myPostList = posts; isLoading = false; }); } catch (e) { setState(() { isLoading = false; }); print('获取数据失败:$e'); } } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: SingleChildScrollView( child: Column( children: [ if (isLoading) const CircularProgressIndicator() // 加载中提示 else if (myPostList.isEmpty) const Text('暂无数据') // 无数据提示 else Text(myPostList[0].body ?? '无内容'), // 空值安全判断 ], ), ), ), ); } }
内容的提问来源于stack exchange,提问作者werner
相关产品推荐
相关产品推荐

