Flutter Web接口数据获取失败,寻求问题排查帮助
Flutter Web 数据获取与展示报错排查
我正在尝试编写第一份Flutter Web代码,从Web API获取数据并在网页上展示。跟随教程操作,但代码无法运行,运行应用时VSCode调试控制台不断输出各类错误。
我推测问题出在状态管理代码中,但无法准确定位具体位置。项目构建为网站并在Chrome中运行。请问我哪里出错了?
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; import '../dtos/dto_objects.dart'; import '../settings/schemes/color_scheme.dart'; import '../components/navbar.dart'; class ContentPage extends StatefulWidget { const ContentPage({super.key}); @override State<ContentPage> createState() => _ContentPageState(); } class _ContentPageState extends State<ContentPage> { var _posts = []; void fetchPosts() async { try { String url = "https://jsonplaceholder.typicode.com/posts"; final response = await get(Uri.parse(url)); final jsonData = jsonDecode(response.body) as List; setState(() { _posts = jsonData; }); } catch (err) {} } @override void initState() { // TODO: implement initState super.initState(); fetchPosts(); } @override Widget build(BuildContext context) { // First prepare dummy items in case fetching from web fails Post dummyCrs1 = new Post(id: "ccc1", userId: "1", title: "Fetching data...", body: "Fetching description..."); Post dummyCrs2 = new Post(id: "ccc2", userId: "1", title: "Fetching data...", body: "Fetching description..."); _posts.add(dummyCrs1); _posts.add(dummyCrs2); return Scaffold( backgroundColor: schemeBackgroundColor, body: ListView( children: [ Center(child: NavBar()), Center( child: ListView.builder( itemCount: _posts.length, itemBuilder: (context, i) { final post = _posts[i]; return Text("Title: ${post["title"]}, Body: ${post["body"]}\n"); } ) ) ] ) ); } }
调试控制台报错截图:
问题分析与修复方案
1. 类型混合错误(核心问题)
build方法会被Flutter频繁调用,每次执行都会向_posts列表添加Post类型的假数据。而API返回的是Map<String, dynamic>类型的列表,最终导致_posts中同时存在两种类型的数据:
- 访问API返回的Map时,
post["title"]是合法的 - 访问假数据的Post对象时,用下标访问属性会直接抛出类型转换错误
修复方式:
- 初始化时就设置好假数据,避免在build方法中重复添加
- API请求成功后,将返回的Map列表转换为统一的
Post对象,保证列表类型一致
2. ListView嵌套布局冲突
外层是可滚动的ListView,内层又嵌套ListView.builder,会出现两个问题:
- 内层ListView没有高度约束,Flutter无法确定其布局尺寸,引发布局错误
- 滚动行为冲突,导致页面滚动异常
修复方式:
- 给内层ListView添加
shrinkWrap: true,让它自适应内容高度 - 添加
physics: NeverScrollableScrollPhysics(),禁用内层ListView的滚动,统一由外层ListView处理滚动
3. 错误捕获无反馈
fetchPosts方法中的catch (err) {}直接吞掉了异常,无法排查API请求失败的原因(比如网络问题、接口错误等)
修复方式:
- 在catch块中打印错误信息,方便调试定位问题
修复后的完整代码
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; import '../dtos/dto_objects.dart'; import '../settings/schemes/color_scheme.dart'; import '../components/navbar.dart'; class ContentPage extends StatefulWidget { const ContentPage({super.key}); @override State<ContentPage> createState() => _ContentPageState(); } class _ContentPageState extends State<ContentPage> { // 初始化时设置假数据,避免在build中重复添加 List<Post> _posts = [ Post(id: "ccc1", userId: "1", title: "Fetching data...", body: "Fetching description..."), Post(id: "ccc2", userId: "1", title: "Fetching data...", body: "Fetching description..."), ]; void fetchPosts() async { try { String url = "https://jsonplaceholder.typicode.com/posts"; final response = await get(Uri.parse(url)); // 先验证请求是否成功 if (response.statusCode == 200) { final jsonData = jsonDecode(response.body) as List; // 将API返回的Map转换为Post对象,保持列表类型统一 setState(() { _posts = jsonData.map((item) => Post( id: item["id"].toString(), userId: item["userId"].toString(), title: item["title"], body: item["body"], )).toList(); }); } else { print("请求失败,状态码:${response.statusCode}"); } } catch (err) { // 打印错误信息,方便调试 print("API请求出错:$err"); } } @override void initState() { super.initState(); fetchPosts(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: schemeBackgroundColor, body: ListView( children: [ Center(child: NavBar()), // 可选:限制内层列表宽度,优化网页端显示 Center( child: SizedBox( width: MediaQuery.of(context).size.width * 0.8, child: ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: _posts.length, itemBuilder: (context, i) { final post = _posts[i]; // 直接访问Post对象的属性,避免类型错误 return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text("Title: ${post.title}\nBody: ${post.body}\n"), ); }, ), ), ) ], ), ); } }
内容的提问来源于stack exchange,提问作者Val
相关产品推荐
相关产品推荐

