Flutter调用HTTP API在PageView.builder展示数据报错求助
问题分析与修复方案
错误根源
- 数据结构访问错误:你尝试通过
data[index]['data']['name']访问数据,但API返回结构并非嵌套data字段,导致data[index]['data']为null,触发[]调用null的异常。 - 未处理请求失败场景:HTTP请求失败时,
data保持初始null值,后续调用data.length或访问元素直接报错。 - FutureBuilder使用不当:每次build都会重复调用
getData()发起请求,且未正确处理加载/错误状态。 - 分页指示器数据源失效:使用空数组
postList生成指示器,导致没有分页点显示。
修复步骤
1. 修正数据获取逻辑
初始化data为空数组,添加异常捕获和错误处理,避免null状态:
List<dynamic> data = []; // 初始化为空数组,而非null Future<void> getData() async { try { final response = await http.get(Uri.parse('https://berequirement.herokuapp.com/products')); if (response.statusCode == 200) { // API直接返回产品数组,无需嵌套data字段 data = jsonDecode(response.body); setState(() {}); // 更新UI } else { print('请求失败,状态码:${response.statusCode}'); } } catch (e) { print('网络请求错误:$e'); } }
2. 优化FutureBuilder使用
在initState中发起请求,避免重复调用,直接通过data的空状态判断加载状态:
@override void initState() { _controller = PageController(initialPage: 0); getData(); // 初始化时仅发起一次请求 super.initState(); } // 替换原FutureBuilder逻辑 child: data.isEmpty ? const Center(child: Text('Loading ...')) : PageView.builder( controller: _controller, itemCount: data.length, onPageChanged: (int index) { setState(() { currentIndex = index; }); }, itemBuilder: (context, index) { final product = data[index]; return Padding( padding: const EdgeInsets.all(40), child: Column( children: [ Text( product['name'], // 直接访问字段,移除无效的['data']层级 style: GoogleFonts.poppins( fontWeight: FontWeight.bold, fontSize: 22, ), ), const SizedBox(height: 20), Text( product['code'], textAlign: TextAlign.center, style: GoogleFonts.poppins( fontWeight: FontWeight.bold, fontSize: 14, color: Colors.grey), ) ], ), ); }, ),
3. 修复分页指示器
将指示器数据源改为data.length,确保分页点正常显示:
Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate( data.length, // 用产品数组长度生成指示器 (index) => buildDot(index, context), ), )
4. 补充缺失的buildDot方法
如果未实现分页点样式,添加以下代码:
Widget buildDot(int index, BuildContext context) { return Container( width: currentIndex == index ? 12 : 8, height: 8, margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( borderRadius: BorderRadius.circular(4), color: currentIndex == index ? Colors.blue : Colors.grey.shade300, ), ); }
完整修正代码
import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { int currentIndex = 0; late PageController _controller; List<dynamic> data = []; @override void initState() { _controller = PageController(initialPage: 0); getData(); super.initState(); } @override void dispose() { _controller.dispose(); super.dispose(); } Future<void> getData() async { try { final response = await http.get(Uri.parse('https://berequirement.herokuapp.com/products')); if (response.statusCode == 200) { data = jsonDecode(response.body); setState(() {}); } else { print('请求失败,状态码:${response.statusCode}'); } } catch (e) { print('网络请求错误:$e'); } } Widget buildDot(int index, BuildContext context) { return Container( width: currentIndex == index ? 12 : 8, height: 8, margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( borderRadius: BorderRadius.circular(4), color: currentIndex == index ? Colors.blue : Colors.grey.shade300, ), ); } @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ Expanded( child: Container( height: 500, width: 300, child: data.isEmpty ? const Center(child: Text('Loading ...')) : PageView.builder( controller: _controller, itemCount: data.length, onPageChanged: (int index) { setState(() { currentIndex = index; }); }, itemBuilder: (context, index) { final product = data[index]; return Padding( padding: const EdgeInsets.all(40), child: Column( children: [ Text( product['name'], style: GoogleFonts.poppins( fontWeight: FontWeight.bold, fontSize: 22, ), ), const SizedBox(height: 20), Text( product['code'], textAlign: TextAlign.center, style: GoogleFonts.poppins( fontWeight: FontWeight.bold, fontSize: 14, color: Colors.grey), ) ], ), ); }, ), ), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate( data.length, (index) => buildDot(index, context), ), ), ], ), ); } }
内容的提问来源于stack exchange,提问作者destructor
相关产品推荐
相关产品推荐

