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

如何在Flutter中使用SharedPreferences保存Radio按钮选中状态

问题分析与修复方案

你的代码存在几个关键问题,导致无法实现需求:

  1. 初始状态设置不严谨:用了一个不在Radio选项范围内的'y'作为默认值,虽首次打开不会选中任何选项,但逻辑上应该用null明确表示未选中状态。
  2. 数据读取后未同步到UI:读取SharedPreferences的值存到了dropdownValueDisease,但Radio组件的groupValue绑定的是level,导致保存的选中状态无法更新到界面。
  3. 变量冗余混乱: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 12:50:28