Flutter开发:如何让DropdownButton选中值跨页面持久保留?
解决方案
你的问题核心原因是:仅在选择区号时做了本地存储,但页面初始化时未读取已存储的选中值,页面重建/跳转返回后变量重置为初始空值,导致下拉框值丢失。
必改步骤(无需引入额外依赖)
- 调整数据加载逻辑,在国家区号JSON加载完成后,读取本地存储的选中值赋值给
_selectedCountryCode,同时增加默认值避免空值报错:
// 修改你的loadJsonData方法 loadJsonData() async { String data = await rootBundle.loadString('assets/country_code.json'); jsonResult = json.decode(data); // 新增:读取已存储的区号 SharedPreferences prefs = await SharedPreferences.getInstance(); String? savedCode = prefs.getString('_selectedCountryCode'); setState(() { // 无存储值时默认选中马来西亚+60,可自行修改默认值 _selectedCountryCode = savedCode ?? "+60"; }); }
- 删减冗余代码:你当前
onChanged回调里重复调用了两次setState和两次存储操作,保留一份即可,避免不必要的性能消耗:
onChanged: (val) async { SharedPreferences prefs = await SharedPreferences.getInstance(); // 只保留StatefulBuilder的setState更新弹窗内状态即可,当前页面的变量赋值和存储写一次就够 setStateSTB(() { _selectedCountryCode = val; prefs.setString('_selectedCountryCode', _selectedCountryCode!); }); // 同步更新当前页面状态 setState(() {}); },
- 增加空值兼容:渲染Dropdown时判断
jsonResult是否加载完成、_selectedCountryCode是否有值,避免加载过程中出现报错:
// 在DropdownButton外层加个判断 child: jsonResult.isNotEmpty && _selectedCountryCode != null ? DropdownButton(/* 原有代码 */) : const CircularProgressIndicator(),
跨页面通用方案(多页面需要展示选中区号时用)
如果多个页面都需要用到该选中的国家区号,建议引入全局状态管理(以GetX为例,Provider等其他方案逻辑同理):
- 定义全局控制器统一管理国家数据和选中值:
import 'package:get/get.dart'; import 'package:flutter/services.dart'; import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; class CountryCodeController extends GetxController { String? selectedCode; List countryList = []; @override void onInit() { super.onInit(); initData(); } initData() async { // 加载本地国家数据 String data = await rootBundle.loadString('assets/country_code.json'); countryList = json.decode(data); // 读取存储的选中值 SharedPreferences prefs = await SharedPreferences.getInstance(); selectedCode = prefs.getString('_selectedCountryCode') ?? "+60"; update(); } saveSelectedCode(String code) async { selectedCode = code; SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setString('_selectedCountryCode', code); update(); } }
- 在
main.dart中全局注册控制器:
void main() { Get.put(CountryCodeController()); runApp(const MyApp()); }
- 所有页面使用时直接读取控制器中的值,修改时调用
saveSelectedCode方法即可全局同步:
// 读取值 final controller = Get.find<CountryCodeController>(); // Dropdown的value赋值为controller.selectedCode // 选择后调用controller.saveSelectedCode(val)
内容的提问来源于stack exchange,提问作者Smile
相关产品推荐
相关产品推荐

