Flutter中SharedPreferences保存多下拉框值异常问题求助
问题描述
在Flutter项目中使用SharedPreferences依赖,期望实现以下功能:
- 首次打开App时,第一个下拉框默认值为
howmany,第二个下拉框默认值为which - 用户选择其他值并点击“next”按钮后,关闭App并清除后台进程,再次打开时显示用户之前选择的值(例如选择“three”和“4th”后重启App仍显示该值)
目前从SharedPreferences获取到null值,无法实现预期效果。
错误原因分析
查看代码后发现核心问题:
- 在读取第二个下拉框存储值的方法中,错误将读取结果赋值给了第一个下拉框的变量
dropdownValueMembers,而非第二个下拉框的dropdownValueNumber,导致第二个下拉框永远无法加载保存的值 - 存储键名
data、data2语义模糊,易引发混淆 - 初始化时的异步方法拆分过细,代码冗余
修复后的完整代码
class _FamilyDetailsScreenState extends State<FamilyDetailsScreen> { // 第一个下拉框:孩子数量 String dropdownValueMembers = 'howmany'; final List<String> memberItems = ['howmany', 'one', 'two', 'three ', 'four ', '5 or more']; // 第二个下拉框:第几个孩子 String dropdownValueNumber = 'which'; final List<String> numberItems = ['which', '1 st', '2 nd', '3 rd ', '4 th ', '5 th']; @override void initState() { super.initState(); _loadSavedValues(); } // 统一加载保存的所有值 Future<void> _loadSavedValues() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); setState(() { // 读取第一个下拉框的值,默认howmany dropdownValueMembers = prefs.getString('number_of_children') ?? 'howmany'; // 读取第二个下拉框的值,默认which dropdownValueNumber = prefs.getString('which_child') ?? 'which'; }); } // 统一保存选中的所有值 Future<void> _saveSelectedValues() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('number_of_children', dropdownValueMembers); await prefs.setString('which_child', dropdownValueNumber); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, resizeToAvoidBottomInset: false, body: Container( child: SafeArea( child: Column( children: <Widget>[ const Text( 'family details', textAlign: TextAlign.center, style: TextStyle( color: Colors.black, fontSize: 18.00, fontWeight: FontWeight.w700, ), ), const SizedBox(height: 30), Padding( padding: const EdgeInsets.only(top: 10, left: 15), child: Row( children: <Widget>[ const Icon( Icons.brightness_1, color: Colors.black, size: 10.0, ), const Padding( padding: EdgeInsets.only(left: 13), child: Text( "Number of children", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600), ), ), Padding( padding: const EdgeInsets.only(left: 2), child: Container( height: 25, decoration: BoxDecoration( boxShadow: const <BoxShadow>[ BoxShadow( color: Color.fromRGBO(0, 0, 0, 0.37), blurRadius: 5) ], color: Colors.white, borderRadius: BorderRadius.circular(15), ), child: DropdownButton( underline: Container(), borderRadius: BorderRadius.circular(20), value: dropdownValueMembers, icon: const Icon(Icons.keyboard_arrow_down), items: memberItems.map((String item) { return DropdownMenuItem( value: item, child: SizedBox( height: 15, width: 120.0, child: Text(item, style: const TextStyle( fontSize: 13.0, fontWeight: FontWeight.w700), textAlign: TextAlign.center), ), ); }).toList(), onChanged: (String? newValue) { setState(() { dropdownValueMembers = newValue!; }); }, ), ), ), ], ), ), const SizedBox(height: 25), Row( children: [ Padding( padding: const EdgeInsets.only(left: 20), child: Text('Which child'), ), Padding( padding: const EdgeInsets.only(left: 100, right: 0, top: 20), child: Container( height: 30, decoration: BoxDecoration( boxShadow: const <BoxShadow>[ BoxShadow( color: Color.fromRGBO(0, 0, 0, 0.37), blurRadius: 5) ], color: Colors.white, borderRadius: BorderRadius.circular(15), ), child: DropdownButton( underline: Container(), borderRadius: BorderRadius.circular(20), value: dropdownValueNumber, icon: const Icon(Icons.keyboard_arrow_down), items: numberItems.map((String item) { return DropdownMenuItem( value: item, child: SizedBox( height: 17, width: 120.0, child: Text(item, style: const TextStyle( fontSize: 13.0, fontWeight: FontWeight.w700), textAlign: TextAlign.center), ), ); }).toList(), onChanged: (String? newNumber) { setState(() { dropdownValueNumber = newNumber!; }); }, ), ), ), ], ), const SizedBox(height: 60), Padding( padding: const EdgeInsets.only(bottom: 0.0, top: 150), child: SizedBox( width: 160.0, height: 35.0, child: ElevatedButton( style: ButtonStyle( shape: MaterialStateProperty.all<RoundedRectangleBorder>( RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), side: const BorderSide(color: Colors.blueAccent), ), ), ), onPressed: _saveSelectedValues, child: const Text('next')), ), ), ], ), ), ), ); } }
修复说明
- 修正变量赋值错误:将第二个下拉框的存储值正确赋值给
dropdownValueNumber,合并加载逻辑为_loadSavedValues,简化初始化流程 - 语义化存储键名:将存储键名改为
number_of_children和which_child,避免混淆 - 优化异步逻辑:合并保存方法为
_saveSelectedValues,统一处理两个下拉框的存储操作,代码更简洁 - 规范变量命名:将列表变量改为
memberItems、numberItems,提升代码可读性
验证步骤
- 首次启动App,两个下拉框分别显示默认值
howmany和which - 选择自定义值后点击“next”按钮
- 关闭App并清除后台进程,重新打开App,下拉框将显示之前选择的值
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

