Flutter从API获取字典列表并展示到DropdownButton的问题
我是Flutter新手,尝试将API数据接入Flutter应用。该API返回的数据里包含一个List<Map>类型的responseObj字段,我希望在应用启动时(initState()阶段)获取数据并展示到DropdownButton中,期望的样式如下:
API地址:http://161.97.96.193:3333/LovLeaveRequest
我的代码如下:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { String? value; List<String> leaveRequest = []; Future<List> get() async { var response = await http.get( Uri.parse("http://161.97.96.193:3333/LovLeaveRequest"), ); if (response.statusCode == 200) { final jsonData = jsonDecode(response.body); return jsonData["responseObj"]; } else { throw Exception(); } } @override void initState() { // leaveRequest = get(); get(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: Container( child: Center( child: DropdownButton<String>( hint: Text('Select Type'), value: this.value, items: leaveRequest.map((item) { return DropdownMenuItem( child: Text(item), value: item, ); }).toList(), onChanged: (value) { setState(() { this.value = value; }); }, ), ), ), ); } }
在initState()中尝试执行leaveRequest = get();时出现以下错误:
类型为'Future
'的值无法分配给类型为'List'的变量。
请尝试更改变量类型,或将右侧类型转换为'List'。
问题分析
get()方法返回的是Future<List>,这是异步操作的结果,不能直接赋值给同步的List<String>变量,必须等待异步操作完成后再处理数据。- API返回的
responseObj是List<Map>,需要从中提取出要显示的字段(比如每个Map里的名称字段),转换成List<String>才能给DropdownButton使用。
修正后的代码
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { String? selectedValue; List<String> leaveRequestOptions = []; bool isLoading = true; // 用于显示加载状态 // 明确返回类型,让代码更清晰 Future<List<Map<String, dynamic>>> fetchLeaveRequests() async { final response = await http.get( Uri.parse("http://161.97.96.193:3333/LovLeaveRequest"), ); if (response.statusCode == 200) { final jsonData = jsonDecode(response.body); return List<Map<String, dynamic>>.from(jsonData["responseObj"]); } else { throw Exception('加载请假类型失败'); } } @override void initState() { super.initState(); _loadLeaveRequests(); // 调用异步加载方法处理数据 } // 处理异步数据加载与转换 void _loadLeaveRequests() async { try { final List<Map<String, dynamic>> data = await fetchLeaveRequests(); // 提取Map中的名称字段(根据API实际返回的键名调整,这里假设是"name") setState(() { leaveRequestOptions = data.map((item) => item["name"].toString()).toList(); isLoading = false; }); } catch (e) { setState(() { isLoading = false; print('加载出错: $e'); // 这里可以添加错误提示UI }); } } @override Widget build(BuildContext context) { return Scaffold( body: Container( padding: EdgeInsets.symmetric(horizontal: 20), child: Center( child: isLoading ? CircularProgressIndicator(color: Colors.blue) // 加载中显示进度圈 : DropdownButton<String>( hint: Text('请选择类型'), value: selectedValue, items: leaveRequestOptions.map((item) { return DropdownMenuItem( child: Text(item), value: item, ); }).toList(), onChanged: (value) { setState(() { selectedValue = value; }); }, isExpanded: true, // 让Dropdown占满父容器宽度 underline: Container( height: 2, color: Colors.blue, // 自定义下划线样式 ), ), ), ), ); } }
关键修改点
- 将原
get()方法重命名为fetchLeaveRequests(),明确返回类型为Future<List<Map<String, dynamic>>>,提升代码可读性。 - 添加
isLoading变量处理加载状态,避免数据未加载完成时Dropdown显示空内容。 - 在
initState()中调用封装的异步方法_loadLeaveRequests(),通过await等待API返回结果,再将List<Map>转换为List<String>并更新页面状态。 - 优化DropdownButton样式,添加
isExpanded和自定义下划线,更贴近期望的展示效果。 - 增加错误捕获逻辑,处理API请求失败的情况。
内容的提问来源于stack exchange,提问作者Asad Sheikh
相关产品推荐
相关产品推荐

