基于Flutter现有模型与API代码,用Future Builder实现id为值、role为文本的下拉按钮
步骤1:添加状态管理变量
在State类中新增两个状态变量,分别用于存储选中的角色ID和标记数据加载状态:
int? _selectedRoleId; bool _isLoading = true;
步骤2:初始化时加载角色数据
在initState中调用接口获取角色数据,完成后更新状态:
@override void initState() { super.initState(); _fetchRoles(); } Future<void> _fetchRoles() async { try { await getRoles(); setState(() { _isLoading = false; }); } catch (e) { print('加载角色失败: $e'); setState(() { _isLoading = false; }); } }
步骤3:实现DropdownButton组件
根据加载状态、数据情况渲染对应UI,核心是将每个RoleModel转为DropdownMenuItem,设置value为角色id,child为角色role文本:
Widget _buildRoleDropdown() { if (_isLoading) { return const CircularProgressIndicator(); } if (roles.isEmpty) { return const Text('暂无角色数据'); } return DropdownButton<int?>( value: _selectedRoleId, hint: const Text('选择角色'), onChanged: (int? newValue) { setState(() { _selectedRoleId = newValue; }); // 可添加选中后的业务逻辑,比如打印选中ID print('选中的角色ID: $newValue'); }, items: roles.map((RoleModel role) { return DropdownMenuItem<int?>( value: role.id, child: Text(role.role ?? '未知角色'), ); }).toList(), ); }
完整示例代码
整合所有代码到一个StatefulWidget中,可直接运行:
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class RoleModel { int? id; String? role; RoleModel({this.id, this.role}); RoleModel.fromJson(Map<String, dynamic> json) { id = json['id']; role = json['role']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = <String, dynamic>{}; data['id'] = id; data['role'] = role; return data; } } class RoleDropdownPage extends StatefulWidget { const RoleDropdownPage({super.key}); @override State<RoleDropdownPage> createState() => _RoleDropdownPageState(); } class _RoleDropdownPageState extends State<RoleDropdownPage> { List<RoleModel> roles = []; int? _selectedRoleId; bool _isLoading = true; Future<List<RoleModel>> getRoles() async { try { final response = await http .get(Uri.parse('https://localhost:8000/roles')); var data = jsonDecode(response.body.toString()); if (response.statusCode == 200) { for (Map<String, dynamic> i in data) { roles.add(RoleModel.fromJson(i)); } return roles; } else { throw Exception('Failed to load roles:$response'); } } catch (e) { throw Exception('Failed due to: $e'); } } @override void initState() { super.initState(); _fetchRoles(); } Future<void> _fetchRoles() async { try { await getRoles(); setState(() { _isLoading = false; }); } catch (e) { print('加载角色失败: $e'); setState(() { _isLoading = false; }); } } Widget _buildRoleDropdown() { if (_isLoading) { return const CircularProgressIndicator(); } if (roles.isEmpty) { return const Text('暂无角色数据'); } return DropdownButton<int?>( value: _selectedRoleId, hint: const Text('选择角色'), onChanged: (int? newValue) { setState(() { _selectedRoleId = newValue; }); print('选中的角色ID: $newValue'); }, items: roles.map((RoleModel role) { return DropdownMenuItem<int?>( value: role.id, child: Text(role.role ?? '未知角色'), ); }).toList(), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('角色选择器')), body: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: _buildRoleDropdown(), ), ), ); } }
关键注意点
- 处理
role为空的情况:用role ?? '未知角色'避免文本显示异常 - 加载状态和空数据状态的处理:提升用户体验
- 选中值的更新:通过
setState触发UI刷新
内容的提问来源于stack exchange,提问作者Jiban Kandel
相关产品推荐
相关产品推荐

