Flutter中如何声明、初始化并使用List<List<String>>?
问题
需求为点击Category组件时,获取并展示对应分类下的items名称。需要为每个分类维护一个String类型列表,尝试使用List<List<String>>但在声明、初始化及赋值过程中多次失败,出现RangeError错误。
尝试的代码片段
代码片段1
List<List<String>> itemsList = [[]]; Container( child: ListView.builder( itemCount: itemsCategories.length , itemBuilder: (context, index) { return Card( child: Column( children: [ InkWell( onTap:() async{ List<String> tempList = await getItems(); // add to list of list for (var element in temp) { itemsList [index].add(element); } print( 'tempList[index] items: ${tempList[index]}'); }, child: Padding( padding: const EdgeInsets.all(8.0), child: Text(itemsCategories[index].name), ), ), ], ), ); } ), )
代码片段2
// assign value one by one for (var i = 0; i < tempList.length; i++) { itemsList[index][i]= tempList [i]; print( itemsList[index][i]); }
错误信息
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0 E/flutter ( 8581): #0 List.[] (dart:core-patch/growable_array.dart:264:36) E/flutter ( 8581): #1 _HomeState.build..
解决方案
1. 正确使用List<List<String>>的方法
初始化
核心问题是初始化时itemsList仅包含一个空列表,但分类数量为itemsCategories.length,当index >=1时,itemsList[index]不存在,触发RangeError。正确初始化需为每个分类提前创建空列表:
// 在State类中声明 List<List<String>> itemsList = []; @override void initState() { super.initState(); // 为每个分类生成一个空列表 itemsList = List.generate(itemsCategories.length, (_) => []); }
赋值操作
点击分类获取数据后,通过setState更新对应索引的列表,确保UI同步刷新:
onTap:() async{ List<String> tempList = await getItems(); // 方式1:直接替换该分类的列表(适用于每次点击重新获取最新数据) setState(() { itemsList[index] = tempList; }); // 方式2:往已有列表追加元素(适用于增量加载场景) // setState(() { // itemsList[index].addAll(tempList); // }); print('分类${index}的items: ${itemsList[index]}'); }
2. 更直观的替代方案:使用Map存储分类与items的对应关系
如果分类有唯一标识(如id或name),使用Map<String, List<String>>可避免索引匹配错误,逻辑更直观:
// 在State类中初始化 Map<String, List<String>> categoryItems = {}; // 点击赋值逻辑 onTap:() async{ List<String> tempList = await getItems(); setState(() { // 以分类名称作为key存储对应items列表 categoryItems[itemsCategories[index].name] = tempList; }); // 通过分类名称直接获取对应items print('${itemsCategories[index].name}的items: ${categoryItems[itemsCategories[index].name]}'); }
3. 展示items的实现
在Card的Column中添加items展示区域,使用嵌套的ListView.builder实现:
Card( child: Column( children: [ InkWell(/* 点击逻辑部分 */), // 仅当当前分类有items时展示 if (itemsList[index].isNotEmpty) ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: itemsList[index].length, itemBuilder: (context, itemIndex) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), child: Text(itemsList[index][itemIndex]), ); }, ), ], ), )
内容的提问来源于stack exchange,提问作者Hesham Elkotabi
相关产品推荐
相关产品推荐

