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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:36:42