Flutter中使用SharedPreferences保存加载应用配置的最佳实践是什么?
现有实现存在几个可优化点:
- 每次存取都调用
SharedPreferences.getInstance(),重复产生异步开销,该方法本身是单例,重复调用也会返回同一个实例,但没必要每次都走异步判断 - 异步加载配置完成后没有调用
setState(),会导致界面第一次加载时不会更新最新的存储状态 - 没有处理存储操作的返回结果,
setBool可能执行失败,直接丢弃返回值会忽略异常场景 - 存储key硬编码,容易出现拼写错误导致存取不匹配
1. 封装统一的SharedPreferences工具类
缓存全局实例,统一管理配置key,示例代码:
// 全局SP工具类 class SpUtil { SpUtil._internal(); static final SpUtil _instance = SpUtil._internal(); factory SpUtil() => _instance; static late final SharedPreferences _sp; // 初始化方法,建议在main函数的runApp之前执行 static Future<void> init() async { _sp = await SharedPreferences.getInstance(); } // 统一管理存储key static const String _keyNotificationEnable = 'notificationIsEnabled'; // 封装存取方法 bool get notificationEnable => _sp.getBool(_keyNotificationEnable) ?? true; Future<bool> setNotificationEnable(bool value) => _sp.setBool(_keyNotificationEnable, value); }
在main函数里提前初始化,避免页面内的异步等待开销:
void main() async { // 确保初始化完成再启动App WidgetsFlutterBinding.ensureInitialized(); await SpUtil.init(); runApp(const MyApp()); }
2. 优化页面实现
class HomePageState extends State<HomePage> with WidgetsBindingObserver { bool notificationIsEnabled = true; void _loadNotificationState() { // 直接同步读取,不需要异步 setState(() { notificationIsEnabled = SpUtil().notificationEnable; }); } Future<void> _saveNotificationState(bool value) async { bool saveSuccess = await SpUtil().setNotificationEnable(value); if (!saveSuccess) { // 可选:存储失败时回滚状态,或者给用户提示 setState(() { notificationIsEnabled = !value; }); } } @override void initState() { super.initState(); // 添加生命周期监听 WidgetsBinding.instance.addObserver(this); _loadNotificationState(); } // 监听应用生命周期变化 @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // 对应Android的onPause回调,应用退到后台时触发 if (state == AppLifecycleState.paused) { // 可以在这里执行批量存储操作,适合多配置项的场景,减少IO次数 _saveNotificationState(notificationIsEnabled); } } @override void dispose() { // 移除生命周期监听,避免内存泄漏 WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Demo App'), actions: [ IconButton( onPressed: () async { bool newState = !notificationIsEnabled; setState(() { notificationIsEnabled = newState; }); // 如果是高频修改的配置,可以不用每次点击都存,统一在退后台时存即可 await _saveNotificationState(newState); }, icon: Icon(notificationIsEnabled ? Icons.notifications_on : Icons.notifications_off), ) ], ), body: const SizedBox.expand(), ); } }
类似Android onPause的生命周期处理说明
Flutter中通过WidgetsBindingObserver监听AppLifecycleState即可实现和Android onPause等效的能力:
AppLifecycleState.paused:应用对用户不可见、无法响应用户输入,进入后台状态,完全对应Android Activity的onPause回调- 适合批量存储修改后的配置、释放资源等操作,避免频繁的IO操作影响前台性能
- 注意必须在
dispose生命周期移除观察者,否则会产生内存泄漏
内容的提问来源于stack exchange,提问作者AliZ.ece
相关产品推荐
相关产品推荐

