如何使用Flutter从MySQL获取数据存入下拉列表并实现二级联动选择
Flutter 实现 MySQL 数据拉取与联动下拉列表的完整方案
核心逻辑说明
Flutter 是客户端框架,禁止直接连接 MySQL 数据库,会暴露数据库账号密码存在严重安全风险。你需要先搭建后端接口对接 MySQL,Flutter 端通过请求接口获取数据后再渲染下拉列表,联动逻辑在客户端状态层实现即可。
实现步骤
1. 后端接口准备
用任意后端语言(Node.js/Java/PHP 等)编写两个接口,对接 MySQL 做数据查询,返回 JSON 格式:
- 接口1:无参数,返回第一个下拉框的全部一级选项数据(示例:省份列表,含
id、name字段) - 接口2:接收一级选项的
id作为请求参数,返回和该ID关联的二级选项列表(示例:对应省份的城市列表,含id、parent_id、name字段)
2. Flutter 端依赖引入
在pubspec.yaml中添加网络请求依赖:
dependencies: flutter: sdk: flutter http: ^1.1.0 # 用于发起接口请求
执行flutter pub get完成依赖安装。
3. 定义数据模型
import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; // 一级选项数据模型 class FirstLevelItem { final String id; final String name; FirstLevelItem({required this.id, required this.name}); factory FirstLevelItem.fromJson(Map<String, dynamic> json) { return FirstLevelItem(id: json['id'], name: json['name']); } } // 二级选项数据模型 class SecondLevelItem { final String id; final String parentId; // 关联一级选项的id final String name; SecondLevelItem({required this.id, required this.parentId, required this.name}); factory SecondLevelItem.fromJson(Map<String, dynamic> json) { return SecondLevelItem( id: json['id'], parentId: json['parent_id'], name: json['name'], ); } }
4. 页面状态与联动逻辑实现
class LinkDropdownPage extends StatefulWidget { const LinkDropdownPage({super.key}); @override State<LinkDropdownPage> createState() => _LinkDropdownPageState(); } class _LinkDropdownPageState extends State<LinkDropdownPage> { // 一级选项相关状态 List<FirstLevelItem> firstLevelList = []; FirstLevelItem? selectedFirstItem; bool firstLoading = false; // 二级选项相关状态 List<SecondLevelItem> secondLevelList = []; SecondLevelItem? selectedSecondItem; bool secondLoading = false; @override void initState() { super.initState(); // 页面初始化拉取一级选项数据 fetchFirstLevelData(); } // 拉取一级选项接口请求 Future<void> fetchFirstLevelData() async { setState(() => firstLoading = true); try { // 替换为你自己的后端接口地址 final res = await http.get(Uri.parse("http://your-api.com/getFirstLevel")); if (res.statusCode == 200) { final List<dynamic> resData = json.decode(res.body); setState(() { firstLevelList = resData.map((e) => FirstLevelItem.fromJson(e)).toList(); }); } } catch (e) { debugPrint("一级数据拉取失败:$e"); } finally { setState(() => firstLoading = false); } } // 选中一级选项后拉取对应二级数据 Future<void> fetchSecondLevelData(String parentId) async { setState(() { secondLoading = true; // 切换一级选项时清空旧的二级数据 selectedSecondItem = null; secondLevelList.clear(); }); try { // 替换为你自己的后端接口地址,携带一级选项id参数 final res = await http.get(Uri.parse("http://your-api.com/getSecondLevel?parentId=$parentId")); if (res.statusCode == 200) { final List<dynamic> resData = json.decode(res.body); setState(() { secondLevelList = resData.map((e) => SecondLevelItem.fromJson(e)).toList(); }); } } catch (e) { debugPrint("二级数据拉取失败:$e"); } finally { setState(() => secondLoading = false); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("联动下拉示例")), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ // 第一个下拉列表 firstLoading ? const CircularProgressIndicator() : DropdownButtonFormField<FirstLevelItem>( decoration: const InputDecoration(labelText: "请选择一级选项"), value: selectedFirstItem, items: firstLevelList.map((item) { return DropdownMenuItem(value: item, child: Text(item.name)); }).toList(), onChanged: (val) { if (val != null) { setState(() => selectedFirstItem = val); // 触发二级数据拉取,实现联动 fetchSecondLevelData(val.id); } }, ), const SizedBox(height: 20), // 第二个下拉列表 secondLoading ? const CircularProgressIndicator() : DropdownButtonFormField<SecondLevelItem>( decoration: const InputDecoration(labelText: "请选择二级选项"), value: selectedSecondItem, items: secondLevelList.map((item) { return DropdownMenuItem(value: item, child: Text(item.name)); }).toList(), onChanged: (val) { setState(() => selectedSecondItem = val); }, disabledHint: const Text("请先选择一级选项"), ), ], ), ), ); } }
额外注意事项
- 如果是纯离线本地场景,可以用 Flutter 的 sqlite 依赖代替 MySQL 存储本地数据,把网络请求逻辑替换成本地数据库查询即可,联动逻辑完全一致
- 后端需要做好跨域配置,否则 Flutter Web 端会请求失败
- 可以自行添加接口请求失败的 Toast 提示,优化用户体验
内容的提问来源于stack exchange,提问作者Asad Amin
相关产品推荐
相关产品推荐

