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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:25:16