You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter从API获取字典列表并展示到DropdownButton的问题

Flutter API数据接入DropdownButton问题解决

我是Flutter新手,尝试将API数据接入Flutter应用。该API返回的数据里包含一个List<Map>类型的responseObj字段,我希望在应用启动时(initState()阶段)获取数据并展示到DropdownButton中,期望的样式如下:
期望Dropdown样式
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'。


问题分析

  1. get()方法返回的是Future<List>,这是异步操作的结果,不能直接赋值给同步的List<String>变量,必须等待异步操作完成后再处理数据。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:05:33