Flutter中如何渲染嵌套数组列表?读取JSON后无法显示数据
解决方案
1. 修复数据赋值问题
你当前在readMenuJson里的setState没有正确更新类的成员变量,局部变量无法被ListView访问。首先在类中定义成员变量:
List<dynamic> menuData = []; // 类的成员变量,用于存储菜单数据
然后修改readMenuJson的赋值逻辑:
Future<void> readMenuJson() async { final response = await rootBundle.loadString('assets/menu_api.json'); final data = json.decode(response); List<dynamic> fetchedData = data["data"]["menu"]; print('NEW DATA = $fetchedData'); setState(() { menuData = fetchedData; // 将接口数据赋值给成员变量 }); }
2. 修复ListView的Text组件错误
menuData[index]是Map类型,不能直接传给Text组件,需要读取具体字段(比如name)。同时为了处理嵌套菜单,我们用自定义组件替代ListTile:
body: ListView.builder( itemCount: menuData.length, itemBuilder: (BuildContext context, int index) { return MenuItemComponent(menuItem: menuData[index]); }, )
3. 实现递归嵌套菜单组件
因为菜单存在多层submenu,需要编写递归组件来渲染每一层:
class MenuItemComponent extends StatelessWidget { final Map<String, dynamic> menuItem; const MenuItemComponent({super.key, required this.menuItem}); @override Widget build(BuildContext context) { bool hasSubmenu = menuItem.containsKey('submenu') && (menuItem['submenu'] as List).isNotEmpty; return ExpansionTile( title: Text(menuItem['name']), leading: menuItem.containsKey('icon') ? const Icon(Icons.menu) // 如需FontAwesome图标,需引入font_awesome_flutter包替换 : null, // 递归渲染子菜单 children: hasSubmenu ? (menuItem['submenu'] as List).map((subItem) => MenuItemComponent(menuItem: subItem)).toList() : [], ); } }
4. 初始化加载数据
在页面的initState中调用数据加载方法:
@override void initState() { super.initState(); readMenuJson(); }
额外注意事项
- 如果你的JSON根结构没有
data字段,直接使用data["menu"]即可,根据实际JSON结构调整。 - 若要使用FontAwesome图标,需在
pubspec.yaml添加依赖:
之后用dependencies: font_awesome_flutter: ^latest_versionFaIcon(FontAwesomeIcons.bars)替换默认图标。
内容的提问来源于stack exchange,提问作者tpies
相关产品推荐
相关产品推荐

