修改Flutter相册示例为列表时遇RangeError,求解决方案
问题解决:Flutter列表赋值导致RangeError错误
错误原因
你代码里的RangeError是因为初始化了空列表futureAlbum = []后,直接通过futureAlbum[index] = fetchAlbum()的方式赋值——空列表没有对应索引的位置,所以触发索引越界错误。
修正方案
方案1:使用add方法添加元素
修改initState中的循环逻辑,用add代替索引赋值:
@override void initState() { super.initState(); for (int index = 0; index < 5; index++) { futureAlbum.add(fetchAlbum()); } }
方案2:初始化列表时指定长度
如果需要提前确定列表长度,可以在初始化时指定长度,再通过索引赋值:
List<Future<EngagementText>> futureAlbum = List.filled(5, Future.value(EngagementText())); @override void initState() { super.initState(); for (int index = 0; index < 5; index++) { futureAlbum[index] = fetchAlbum(); } }
额外优化:批量处理多个Future请求
如果需要等待所有请求完成后再展示数据,推荐用Future.wait批量处理:
late Future<List<EngagementText>> futureEngagementTexts; @override void initState() { super.initState(); // 批量发起5个请求,等待全部完成 futureEngagementTexts = Future.wait(List.generate(5, (_) => fetchAlbum())); }
对应的FutureBuilder也需要调整为处理列表数据:
FutureBuilder<List<EngagementText>>( future: futureEngagementTexts, builder: (context, snapshot) { if (snapshot.hasData) { // 展示第4个元素(索引3)的text return Text(snapshot.data![3].text ?? '无内容'); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } return const CircularProgressIndicator(); }, )
完整修正后的代码
import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; Future<EngagementText> fetchAlbum() async { final response = await http.get(Uri.parse( 'https://ListeningToGod.org/SermonEngagement/TextFiles/2024-09-0801a.json')); if (response.statusCode == 200) { return EngagementText.fromJson( jsonDecode(response.body) as Map<String, dynamic>); } else { throw Exception('Failed to load album'); } } class EngagementText { String? version; String? date; String? text; List<Links>? links; EngagementText({this.version, this.date, this.text, this.links}); EngagementText.fromJson(Map<String, dynamic> json) { try { version = json['version']; date = json['date']; text = json['text']; if (json['links'] != null) { links = <Links>[]; json['links'].forEach((v) { links!.add(Links.fromJson(v)); }); } } catch (e) { date = "2024-01-01"; text = "Dummy Text"; } } Map<String, dynamic> toJson() { final Map<String, dynamic> data = <String, dynamic>{}; data['version'] = version; data['date'] = date; data['text'] = text; if (links != null) { data['links'] = links!.map((v) => v.toJson()).toList(); } return data; } } class Links { String? link; String? text; Links({this.link, this.text}); Links.fromJson(Map<String, dynamic> json) { link = json['link']; text = json['text']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = <String, dynamic>{}; data['link'] = link; data['text'] = text; return data; } } void main() => runApp(const MyApp()); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { List<Future<EngagementText>> futureAlbum = []; @override void initState() { super.initState(); // 用add方法添加元素,避免索引越界 for (int index = 0; index < 5; index++) { futureAlbum.add(fetchAlbum()); } } @override Widget build(BuildContext context) { return MaterialApp( title: 'Fetch Data Example', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), ), home: Scaffold( appBar: AppBar( title: const Text('Fetch Data Example'), ), body: Center( child: FutureBuilder<EngagementText>( future: futureAlbum[3], builder: (context, snapshot) { if (snapshot.hasData) { return Text(snapshot.data!.text ?? '无内容'); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } return const CircularProgressIndicator(); }, ), ), ), ); } }
内容的提问来源于stack exchange,提问作者rjapenga
相关产品推荐
相关产品推荐

