Flutter:如何通过接口数据动态生成Drawer中的ListTile?
问题描述
我通过fetchMenus()方法从接口获取菜单名称列表,希望将这些名称显示在Drawer的ListTile的Text组件中,请问该如何实现?
以下是我的相关代码:
模型类
class Menu { const Menu({ required this.name, required this.folder, }); final String name; final String folder; factory Menu.fromJson(Map<String, dynamic> json) => Menu( name: json["name"], folder: json["folder"], ); Map<String, dynamic> toJson() => { "name": name, "folder": folder, }; }
接口请求代码
Future<List<Menu>> fetchMenus() async { final response = await http.get(Uri.parse('http://myUrl:3355/')); if (response.statusCode == 200) { var getMenusData = json.decode(response.body) as List; var listMenus = getMenusData.map((i) => Menu.fromJson(i)).toList(); return listMenus; } else { throw Exception('Failed to load Menus'); } }
待修改的Drawer代码
Drawer( child: ListView( padding: EdgeInsets.zero, children: [ const DrawerHeader( decoration: BoxDecoration( color: Colors.blue, ), child: Text('Drawer Header'), ), ListTile( title: const Text('Item 1'), onTap: () { }, ), ListTile( title: const Text('Item 2'), onTap: () { }, ), ], ), );
解决方案
方法一:使用FutureBuilder(推荐)
直接用FutureBuilder包裹Drawer内的ListView,处理异步数据的加载、成功、失败状态:
Drawer( child: FutureBuilder<List<Menu>>( future: fetchMenus(), builder: (context, snapshot) { // 加载中显示加载指示器 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } // 加载失败显示错误信息 if (snapshot.hasError) { return Center(child: Text('加载失败: ${snapshot.error}')); } // 加载成功,遍历菜单生成ListTile final menus = snapshot.data ?? []; return ListView( padding: EdgeInsets.zero, children: [ const DrawerHeader( decoration: BoxDecoration( color: Colors.blue, ), child: Text('Drawer Header'), ), ...menus.map((menu) => ListTile( title: Text(menu.name), onTap: () { // 可在此添加点击逻辑,比如根据menu.folder执行对应操作 Navigator.pop(context); }, )), ], ); }, ), );
方法二:在StatefulWidget中手动管理状态
如果需要更灵活的状态控制(比如支持重新加载、下拉刷新),可以将数据托管在State类中:
class YourPage extends StatefulWidget { const YourPage({super.key}); @override State<YourPage> createState() => _YourPageState(); } class _YourPageState extends State<YourPage> { late Future<List<Menu>> _menusFuture; @override void initState() { super.initState(); // 页面初始化时加载菜单数据 _menusFuture = fetchMenus(); } // 重新加载菜单的方法 void _reloadMenus() { setState(() { _menusFuture = fetchMenus(); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('页面标题')), drawer: Drawer( child: FutureBuilder<List<Menu>>( future: _menusFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('加载失败: ${snapshot.error}'), const SizedBox(height: 16), TextButton( onPressed: _reloadMenus, child: const Text('重新加载'), ), ], ); } final menus = snapshot.data ?? []; return ListView( padding: EdgeInsets.zero, children: [ const DrawerHeader( decoration: BoxDecoration(color: Colors.blue), child: Text('Drawer Header'), ), ...menus.map((menu) => ListTile( title: Text(menu.name), onTap: () { Navigator.pop(context); // 自定义点击后的逻辑,比如跳转页面 }, )), ], ); }, ), ), body: const Center(child: Text('页面内容')), ); } }
注意事项
- 确保已在
pubspec.yaml中添加http依赖并执行flutter pub get:
dependencies: flutter: sdk: flutter http: ^1.1.0
- 可根据需求扩展异常处理逻辑,比如无网络时的提示
- 若菜单数据需要全局共享,可结合Provider、Bloc等状态管理工具实现
内容的提问来源于stack exchange,提问作者Mahsun Işık
相关产品推荐
相关产品推荐

