如何在Flutter中使用SharedPreferences保存Radio按钮选中状态
问题分析与修复方案
你的代码存在几个关键问题,导致无法实现需求:
- 初始状态设置不严谨:用了一个不在Radio选项范围内的
'y'作为默认值,虽首次打开不会选中任何选项,但逻辑上应该用null明确表示未选中状态。 - 数据读取后未同步到UI:读取SharedPreferences的值存到了
dropdownValueDisease,但Radio组件的groupValue绑定的是level,导致保存的选中状态无法更新到界面。 - 变量冗余混乱:
dropdownValueDisease变量与功能无关,属于无效冗余代码。
以下是修正后的完整代码:
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class RadioButtonScreen extends StatefulWidget { const RadioButtonScreen({Key? key}) : super(key: key); @override State<RadioButtonScreen> createState() => _RadioButtonScreenState(); } class _RadioButtonScreenState extends State<RadioButtonScreen> { // 用可空类型表示未选中状态,初始值为null String? selectedOption; @override void initState() { super.initState(); // 初始化时读取保存的选中状态 _loadSelectedOption(); } // 保存选中的选项到SharedPreferences _saveSelectedOption(String option) async { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString("selected_option", option); } // 从SharedPreferences读取保存的选项 _loadSelectedOption() async { SharedPreferences prefs = await SharedPreferences.getInstance(); setState(() { selectedOption = prefs.getString("selected_option"); }); } @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; return Scaffold( body: Container( child: Column( children: [ SizedBox( height: height * 0.72, width: MediaQuery.of(context).size.width, child: Column( children: <Widget>[ const SizedBox(height: 10), // Radio选项:taking ListTile( minLeadingWidth: 1, leading: const Icon(Icons.brightness_1, color: Colors.black, size: 10.0), title: const Text("taking", style: TextStyle(fontSize: 13.3, fontWeight: FontWeight.w800)), trailing: Radio( value: "taking", groupValue: selectedOption, onChanged: (value) { setState(() { selectedOption = value.toString(); }); }, ), ), // Radio选项:grow ListTile( minLeadingWidth: 1, leading: const Icon(Icons.brightness_1, color: Colors.black, size: 10.0), title: const Text("grow", style: TextStyle(fontSize: 13.3, fontWeight: FontWeight.w800)), trailing: Radio( value: "grow", groupValue: selectedOption, onChanged: (value) { setState(() { selectedOption = value.toString(); }); }, ), ), // Radio选项:listing ListTile( minLeadingWidth: 1, leading: const Icon(Icons.brightness_1, color: Colors.black, size: 10.0), title: const Text("listing", style: TextStyle(fontSize: 13.3, fontWeight: FontWeight.w800)), trailing: Radio( value: "listing", groupValue: selectedOption, onChanged: (value) { setState(() { selectedOption = value.toString(); }); }, ), ), // Radio选项:eye ListTile( minLeadingWidth: 1, leading: const Icon(Icons.brightness_1, color: Colors.black, size: 10.0), title: const Text("eye", style: TextStyle(fontSize: 13.3, fontWeight: FontWeight.w800)), trailing: Radio( value: "eye", groupValue: selectedOption, onChanged: (value) { setState(() { selectedOption = value.toString(); }); }, ), ), // Radio选项:autism ListTile( minLeadingWidth: 1, leading: const Icon(Icons.brightness_1, color: Colors.black, size: 10.0), title: const Text("autism", style: TextStyle(fontSize: 13.3, fontWeight: FontWeight.w800)), trailing: Radio( value: "autism", groupValue: selectedOption, onChanged: (value) { setState(() { selectedOption = value.toString(); }); }, ), ), ], ), ), Padding( padding: const EdgeInsets.only(bottom: 0.0), 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: () { if (selectedOption != null) { _saveSelectedOption(selectedOption!); // 可添加关闭页面/应用的逻辑,比如Navigator.pop(context); } }, child: const Text('next'), ), ), ), ], ), ), ); } }
关键修改点说明:
- 将
level改为可空的selectedOption,初始值设为null,确保首次打开时所有Radio都处于未选中状态。 - 移除冗余的
dropdownValueDisease变量,直接操作selectedOption,保证数据读取和UI展示的一致性。 - 修正
_loadSelectedOption方法,将读取到的值直接赋值给selectedOption并调用setState更新UI。 - 在next按钮的点击事件中增加非空判断,避免保存null值。
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

