Flutter中Shared Preferences无法正常存取变量数据问题求解
问题核心原因
你的代码存在4个直接导致持久化失效的逻辑错误:
- SharedPreferences写入逻辑错误:
_setPassKEYSharedPref方法里写入的是写死的字符串字面量'enteredPassKEY',不是实际的有效密钥值,相当于每次存的都是无效内容,重启后自然读不到认证状态。 - 变量作用域错误:把
enteredPassKEY、authIcon定义为顶层全局变量,没有放在页面State中托管,状态更新时容易出现上下文不同步的问题。 - 校验逻辑断层:
checkPassKey方法直接读取全局变量enteredPassKEY做比对,但这个变量从未绑定用户输入框的实际输入内容,哪怕用户输入了正确密钥,也进不了校验通过的分支。 - 冗余状态更新:
_getVarSharedPref方法里已经包裹了setState,内部又嵌套了一层setState,会触发不必要的重绘,极端情况下会导致状态更新不生效。
修复方案
按以下步骤调整即可实现预期效果:
- 移除顶层全局状态变量,将输入控制器、认证图标、密钥常量全部放到
_MyHomePageState类内部管理 - 新增文本编辑控制器,绑定到密码输入框,实时获取用户输入的密钥内容
- 修正SharedPreferences写入逻辑:密钥校验通过后,将正确的密钥值写入本地存储,不要写入固定字面量
- 移除冗余的嵌套
setState,启动时读取本地存储的认证状态,直接初始化图标样式 - 补充输入框资源释放逻辑,避免内存泄漏
修复后完整可运行代码
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() { runApp(MaterialApp( debugShowCheckedModeBanner: false, title: 'Organizer', initialRoute: '/home', routes: { '/home': (context) => const MyHomePage(), } )); } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { // 密钥输入框控制器 final _passkeyController = TextEditingController(); // 认证状态图标,默认未认证 Widget _authIcon = const Icon(Icons.lock, color: Colors.redAccent); // 硬编码正确密钥 static const String _validPasskey = 'ThisIsPassword'; @override void initState() { super.initState(); // 启动时加载本地存储的认证状态 _loadSavedAuthStatus(); } @override void dispose() { // 释放输入框控制器资源 _passkeyController.dispose(); super.dispose(); } // 读取本地存储的认证状态 Future<void> _loadSavedAuthStatus() async { final prefs = await SharedPreferences.getInstance(); final savedKey = prefs.getString('passKEY'); if (savedKey == _validPasskey) { setState(() { _authIcon = const Icon(Icons.check_circle_sharp, color: Colors.greenAccent); }); } } // 密钥校验逻辑 void _checkPassKey() async { final inputContent = _passkeyController.text.trim(); if (inputContent == _validPasskey) { // 校验通过先更新UI setState(() { _authIcon = const Icon(Icons.check_circle_sharp, color: Colors.greenAccent); }); // 写入持久化存储 final prefs = await SharedPreferences.getInstance(); await prefs.setString('passKEY', _validPasskey); // 弹出成功提示 if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('认证成功')) ); } } else { // 密钥错误提示 ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('密钥错误,请重新输入'), backgroundColor: Colors.redAccent, ) ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('认证页面'), actions: [ // 显示认证状态图标 Padding( padding: const EdgeInsets.only(right: 16), child: _authIcon, ) ], ), body: Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( controller: _passkeyController, obscureText: true, decoration: const InputDecoration( labelText: '请输入Pass key', border: OutlineInputBorder(), ), ), const SizedBox(height: 24), MaterialButton( color: Colors.blue, textColor: Colors.white, onPressed: _checkPassKey, child: const Text('提交验证'), ) ], ), ), ); } }
修复后首次输入正确密钥
ThisIsPassword会自动持久化认证状态,杀掉应用重新打开会直接读取状态显示认证成功图标,不需要重复输入密钥。
内容的提问来源于stack exchange,提问作者Nehal Hosalikar
相关产品推荐
相关产品推荐

