Flutter FutureBuilder持续处于ConnectionState.waiting状态问题求助
解决Flutter FutureBuilder一直停在waiting状态及数组越界问题
先梳理你代码里的几个关键问题:
- FutureBuilder的future重复执行导致无限循环
你在build方法里直接写future: fetchData(),每次页面重建(比如setState触发)都会重新调用fetchData,而fetchData里的setState又会触发build,形成死循环,所以ConnectionState一直处于waiting。 - fetchData没有返回值,FutureBuilder无法获取异步结果
你声明了Future<dynamic>但没有return任何数据,还通过setState维护外部变量three,这违背了FutureBuilder的设计逻辑——它应该直接使用future返回的快照数据,不需要额外维护状态变量。 - 直接访问数组索引导致越界
初始时three是空数组,three[1]必然触发索引越界错误,必须先判断数据是否加载完成且数组长度足够。
修复后的完整代码
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class DartPad extends StatefulWidget { const DartPad({Key? key}) : super(key: key); @override State<DartPad> createState() => _DartPadState(); } class _DartPadState extends State<DartPad> { // 将future存为成员变量,避免每次build重复执行请求 late Future<List<dynamic>> _fetchDataFuture; Future<List<dynamic>> fetchData() async { var sheetID = '1j7sYExCP0etGw_LoxqYTFRrjwHmJv73SHzC26jbtpH4'; var sheetTab = 'daftar'; var url = Uri.parse('https://opensheet.elk.sh/$sheetID/$sheetTab'); final response = await http.get(url); // 直接解析并返回数据,无需setState return json.decode(response.body) as List<dynamic>; } @override void initState() { // 在initState中初始化future,只执行一次网络请求 _fetchDataFuture = fetchData(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( centerTitle: true, title: const Text('Dartpad'), ), body: FutureBuilder<List<dynamic>>( // 使用预先初始化的future,避免重复请求 future: _fetchDataFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: Text('Loading....')); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('没有数据')); } else { final dataList = snapshot.data!; // 方式1:展示单个数据(索引1的nama) // return Center(child: Text(dataList[1]['nama'] ?? '无名称')); // 方式2:循环展示所有数据(推荐) return ListView.builder( itemCount: dataList.length, itemBuilder: (context, index) { final item = dataList[index]; return ListTile( title: Text(item['nama'] ?? '无名称'), subtitle: Text(item['alamat'] ?? ''), // 替换为你需要的其他字段 ); }, ); } }, ), ); } }
关键修改说明
- 将future存为成员变量:在
initState中初始化_fetchDataFuture,确保网络请求只执行一次,避免build时重复触发请求。 - fetchData返回解析后的数据:不再依赖
setState更新外部变量,让FutureBuilder直接通过snapshot获取异步结果。 - 完善状态判断逻辑:依次处理waiting、error、无数据的情况,最后再处理成功加载的数据,彻底避免数组越界。
- 循环展示数据:用
ListView.builder遍历所有数据,既安全又满足你展示全部内容的需求。
内容的提问来源于stack exchange,提问作者Eli
相关产品推荐
相关产品推荐

