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

Flutter开发:如何将API数据加载到Dropdown组件?求助

问题:Flutter Dropdown组件无法加载API返回的数据

问题描述

本地字符串列表能正常加载到Dropdown组件,但调用API获取数据时,Dropdown无任何内容显示,结果为空。

API请求代码

Future<List<Agama>> getAgama() async {
    String url = Constant.baseURL;
    String token = await UtilSharedPreferences.getToken();
    final response = await http.get(
      Uri.parse(
        '$url/auth/mhs_siakad/dosen',
      ),
      headers: {
        'Authorization': 'Bearer $token',
      },
    );
    print(response.statusCode);
    print(response.body);
    if (response.statusCode == 200) {
      final result =
          json.decode(response.body)['nm_agama'] as Map<String, dynamic>;
      UserBiodata agama = UserBiodata.fromJson(result);
      List<Agama> l = agama.data ?? [];
      return l;
    } else {
      throw Exception();
    }
  }

Widget代码

List<Agama>? religion = [];

 @override
  void initState() {
    super.initState();
    BiodataProvider().getAgama();
  }

  var dropdownAgama;
...
     FutureBuilder(
                future: BiodataProvider().getBiodata(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    print(' ini Agama $religion');
                    return Column(
                      children: [
                        Text(
                          snapshot.data!.data!.name.toString(),
                          style: bold5,
                        ),
                        DropdownButton(
                          hint: const Text('Religion'),
                          items: religion!.map((item) {
                            return DropdownMenuItem(
                              value: item.nmAgama.toString(),
                              child: Text(item.idAgama.toString()),
                            );
                          }).toList(),
                          onChanged: (newVal) {
                            setState(() {
                              dropdownAgama = newVal;
                            });
                          },
                          value: dropdownAgama,
                        ),
                      ],
                    );
                  } else {
                    return const Text('No Data');
                  }
                }),
...

数据模型代码

class Agama {
  String? id;
  String? idAgama;
  String? nmAgama;
  String? createdAt;
  String? updatedAt;
  dynamic createdBy;
  dynamic updatedBy;

  Agama(
      {this.id,
      this.idAgama,
      this.nmAgama,
      this.createdAt,
      this.updatedAt,
      this.createdBy,
      this.updatedBy});

  Agama.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    idAgama = json['id_agama'];
    nmAgama = json['nm_agama'];
    createdAt = json['created_at'];
    updatedAt = json['updated_at'];
    createdBy = json['created_by'];
    updatedBy = json['updated_by'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['id_agama'] = idAgama;
    data['nm_agama'] = nmAgama;
    data['created_at'] = createdAt;
    data['updated_at'] = updatedAt;
    data['created_by'] = createdBy;
    data['updated_by'] = updatedBy;
    return data;
  }
}

API返回数据截图

API返回数据


问题分析与修复方案

核心问题点

  1. API解析逻辑错误:从截图看,API返回的是包含data数组的对象,但你代码里错误地取了nm_agama字段,且将其当作Map解析,完全不符合返回结构。
  2. 未更新UI状态:调用getAgama()后,没有将返回结果赋值给religion列表,也没调用setState触发UI更新。
  3. FutureBuilder绑定错误:当前FutureBuilder关联的是getBiodata(),与宗教数据加载无关,无法监听getAgama()的状态变化。

修复步骤

1. 修正API解析逻辑

修改getAgama方法,正确解析返回的数组数据:

Future<List<Agama>> getAgama() async {
  String url = Constant.baseURL;
  String token = await UtilSharedPreferences.getToken();
  final response = await http.get(
    Uri.parse('$url/auth/mhs_siakad/dosen'),
    headers: {'Authorization': 'Bearer $token'},
  );
  print(response.statusCode);
  print(response.body);
  if (response.statusCode == 200) {
    // 直接提取data数组
    final List<dynamic> resultList = json.decode(response.body)['data'];
    // 将数组元素逐个转为Agama对象
    return resultList.map((item) => Agama.fromJson(item)).toList();
  } else {
    throw Exception('加载宗教数据失败');
  }
}

2. 正确获取并更新数据

在Widget中新增加载方法,获取数据后更新状态:

List<Agama>? religion = [];

@override
void initState() {
  super.initState();
  _loadReligionData();
}

void _loadReligionData() async {
  try {
    List<Agama> data = await BiodataProvider().getAgama();
    setState(() {
      religion = data;
    });
  } catch (e) {
    print('加载失败:$e');
  }
}

3. 优化Dropdown的FutureBuilder(可选)

如果需要等待宗教数据加载完成再显示Dropdown,可单独为Dropdown绑定FutureBuilder:

// 替换原Dropdown代码
FutureBuilder<List<Agama>>(
  future: BiodataProvider().getAgama(),
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return DropdownButton(
        hint: const Text('选择宗教'),
        items: snapshot.data!.map((item) {
          return DropdownMenuItem(
            value: item.nmAgama,
            child: Text(item.nmAgama.toString()), // 建议显示宗教名称而非ID
          );
        }).toList(),
        onChanged: (newVal) {
          setState(() {
            dropdownAgama = newVal;
          });
        },
        value: dropdownAgama,
      );
    } else if (snapshot.hasError) {
      return Text('加载失败:${snapshot.error}');
    } else {
      return const CircularProgressIndicator();
    }
  },
),

额外提示

  • 检查UserBiodata类是否多余,API返回结构不需要额外的包装类,可直接解析data数组。
  • Dropdown的选项文本建议显示nmAgama(宗教名称),而非idAgama,提升用户体验。

内容的提问来源于stack exchange,提问作者sharon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:01:13