Flutter中如何从gRPC API为下拉按钮添加选项
实现基于gRPC服务数据的Flutter下拉菜单
第一步:完善你的gRPC数据获取方法
你当前的fetchItemsh方法有两处需要修正:
- 把
port: ----替换为实际的gRPC服务端口(比如常用的50051) - 必须在请求完成后关闭ClientChannel,避免资源泄漏,将客户端关闭逻辑放到
finally块中
修正后的代码:
Future<GroupsStates?> fetchItemsh() async { final client = ClientChannel( LoginState.ipServerController.text, port: 50051, // 替换为你的实际服务端口 options: ChannelOptions( credentials: ChannelCredentials.insecure(), ), ); final stub = EngineClient(client); try { var result = await stub.groupsStatesAll(Void()); return result; } catch (e) { print('捕获错误: $e'); return null; } finally { await client.shutdown(); // 确保请求结束后释放客户端资源 } }
第二步:在Widget中实现下拉菜单逻辑
用StatefulWidget结合FutureBuilder处理异步数据的加载、错误和展示,以下是完整示例(假设你的GroupsStates proto定义包含List<GroupState> groups字段,请根据实际proto结构调整):
class GrpcDropdown extends StatefulWidget { const GrpcDropdown({super.key}); @override State<GrpcDropdown> createState() => _GrpcDropdownState(); } class _GrpcDropdownState extends State<GrpcDropdown> { GroupState? _selectedItem; // 存储选中的下拉选项 @override Widget build(BuildContext context) { return FutureBuilder<GroupsStates?>( future: fetchItemsh(), builder: (context, snapshot) { // 加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } // 错误或无数据状态 if (snapshot.hasError || snapshot.data == null) { return const Center(child: Text('加载数据失败')); } final itemList = snapshot.data!.groups; // 空数据状态 if (itemList.isEmpty) { return const Center(child: Text('无可用选项')); } // 构建下拉菜单 return DropdownButtonFormField<GroupState>( value: _selectedItem, hint: const Text('选择分组'), onChanged: (GroupState? newValue) { setState(() { _selectedItem = newValue; }); }, items: itemList.map((GroupState item) { return DropdownMenuItem<GroupState>( value: item, child: Text(item.name), // 替换为你要显示的选项文本字段,比如item.id ); }).toList(), ); }, ); } }
关键注意事项
- 不要直接把
fetchItemsh()写在FutureBuilder的future参数里(会导致每次build都重新请求),如果需要刷新数据,建议在initState或按钮点击事件中触发 - 根据你的ProtoBuf定义调整
GroupState的字段访问逻辑,确保显示的文本是正确的业务字段 - 生产环境请使用
ChannelCredentials.secure()替代insecure(),保证通信安全
内容的提问来源于stack exchange,提问作者mary
相关产品推荐
相关产品推荐

