Flutter中如何将API参数接入Dropdown组件?求实现示例
实现Dropdown选中值作为API参数发起请求的示例
核心思路
你的API需要int类型的semester参数,不能直接用字符串列表绑定Dropdown,必须把显示文本和对应API参数值绑定,选中后用匹配的数值发起请求。
步骤1:定义绑定参数的学期选项
替换原静态字符串列表,改用包含显示文本与对应参数值的结构:
// 绑定学期显示文本与API需要的int参数 List<Map<String, dynamic>> semesterOptions = [ {"text": "第1学期", "value": 1}, {"text": "第2学期", "value": 2}, {"text": "第3学期", "value": 3}, {"text": "第4学期", "value": 4}, {"text": "第5学期", "value": 5}, {"text": "第6学期", "value": 6}, ]; int selectedSemester = 1; // 默认选中第1学期 List<Data> data = []; bool isLoading = false; // 加载状态标记
步骤2:修改Dropdown组件适配参数绑定
调整Dropdown的选项生成与选中逻辑,确保存储的是API所需的int参数:
Container( padding: const EdgeInsets.only(left: 12, right: 8), width: double.infinity, height: 50, decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 9, offset: const Offset(1, 2), ), ], ), child: DropdownButtonHideUnderline( child: DropdownButton<int>( value: selectedSemester, hint: const Text("选择学期"), onChanged: (int? newValue) { if (newValue != null) { setState(() { selectedSemester = newValue; }); // 可选:选中后立即发起请求,替代按钮触发 // fetchNilaiMahasiswa(); } }, items: semesterOptions.map((option) { return DropdownMenuItem<int>( value: option["value"], child: Text(option["text"]), ); }).toList(), ), ), ), // 添加请求触发按钮(避免频繁请求) ElevatedButton( onPressed: isLoading ? null : fetchNilaiMahasiswa, child: isLoading ? const CircularProgressIndicator(size: 20) : const Text("获取成绩"), ),
步骤3:完善API请求与状态更新
封装请求方法,处理加载状态、数据更新与异常捕获:
Future<void> fetchNilaiMahasiswa() async { setState(() { isLoading = true; }); try { NilaiMahasiswa result = await getNilaiMahasiswa(selectedSemester); setState(() { data = result.data; // 假设NilaiMahasiswa包含Data类型的列表字段 isLoading = false; }); } catch (e) { setState(() { isLoading = false; }); // 异常提示,可替换为弹窗 print("请求失败: $e"); } } // 保留你原有的API请求方法 Future<NilaiMahasiswa> getNilaiMahasiswa(int semester) async { String url = Constant.baseURL; String token = await UtilSharedPreferences.getToken(); final response = await http.get( Uri.parse('$url/auth/mhs_siakad/transkrip_nilai?semester=$semester'), headers: {'Authorization': 'Bearer $token'}, ); print(response.statusCode); print(response.body); if (response.statusCode == 200) { return NilaiMahasiswa.fromJson(jsonDecode(response.body)); } else { throw Exception('获取成绩失败'); } }
完整StatefulWidget示例
将以上代码整合为完整页面:
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; // 导入你的Constant、UtilSharedPreferences、NilaiMahasiswa、Data类 class NilaiMahasiswaPage extends StatefulWidget { const NilaiMahasiswaPage({super.key}); @override State<NilaiMahasiswaPage> createState() => _NilaiMahasiswaPageState(); } class _NilaiMahasiswaPageState extends State<NilaiMahasiswaPage> { List<Map<String, dynamic>> semesterOptions = [ {"text": "第1学期", "value": 1}, {"text": "第2学期", "value": 2}, {"text": "第3学期", "value": 3}, {"text": "第4学期", "value": 4}, {"text": "第5学期", "value": 5}, {"text": "第6学期", "value": 6}, ]; int selectedSemester = 1; List<Data> data = []; bool isLoading = false; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('学生成绩查询')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ // Dropdown组件 Container( padding: const EdgeInsets.only(left: 12, right: 8), width: double.infinity, height: 50, decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 9, offset: const Offset(1, 2), ), ], ), child: DropdownButtonHideUnderline( child: DropdownButton<int>( value: selectedSemester, hint: const Text("选择学期"), onChanged: (int? newValue) { if (newValue != null) { setState(() { selectedSemester = newValue; }); } }, items: semesterOptions.map((option) { return DropdownMenuItem<int>( value: option["value"], child: Text(option["text"]), ); }).toList(), ), ), ), const SizedBox(height: 20), // 请求按钮 ElevatedButton( onPressed: isLoading ? null : fetchNilaiMahasiswa, style: ElevatedButton.styleFrom( minimumSize: const Size(double.infinity, 50), ), child: isLoading ? const CircularProgressIndicator(color: Colors.white, size: 20) : const Text("获取成绩", style: TextStyle(fontSize: 16)), ), const SizedBox(height: 20), // 数据展示区域 Expanded( child: isLoading ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: data.length, itemBuilder: (context, index) { // 根据你的Data类结构自定义列表项 return ListTile( title: Text(data[index].mataKuliah), // 示例字段 subtitle: Text('成绩: ${data[index].nilai}'), // 示例字段 ); }, ), ), ], ), ), ); } Future<void> fetchNilaiMahasiswa() async { setState(() { isLoading = true; }); try { NilaiMahasiswa result = await getNilaiMahasiswa(selectedSemester); setState(() { data = result.data; isLoading = false; }); } catch (e) { setState(() { isLoading = false; }); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('请求失败: $e')), ); } } } Future<NilaiMahasiswa> getNilaiMahasiswa(int semester) async { String url = Constant.baseURL; String token = await UtilSharedPreferences.getToken(); final response = await http.get( Uri.parse('$url/auth/mhs_siakad/transkrip_nilai?semester=$semester'), headers: {'Authorization': 'Bearer $token'}, ); print(response.statusCode); print(response.body); if (response.statusCode == 200) { return NilaiMahasiswa.fromJson(jsonDecode(response.body)); } else { throw Exception('服务器返回错误: ${response.statusCode}'); } } }
内容的提问来源于stack exchange,提问作者sharon
相关产品推荐
相关产品推荐

