如何将Provider声明的变量像SharedPreferences一样持久化存储?
要让配置修改在重启后保留,需在CountPage中集成SharedPreferences,实现加载持久化数据和修改状态时自动保存的逻辑,具体步骤如下:
1. 重构CountPage类,添加持久化逻辑
SharedPreferences仅支持存储基础数据类型(字符串、数字、布尔值),因此需要将TextAlign和Color转换为可存储格式,再在加载时还原:
- 添加
SharedPreferences实例变量 - 实现
init和loadPreferences方法,启动时加载保存的配置 - 每个修改状态的方法中,增加保存到
SharedPreferences的逻辑
修改后的CountPage代码:
import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class CountPage extends ChangeNotifier { late SharedPreferences _prefs; int _page = 150; int get page => _page; bool _visible = false; bool get visible => _visible; double _font = 40; double get font => _font; TextAlign align = TextAlign.center; Color selection = Colors.red[200]!; // 初始化SharedPreferences并加载配置 Future<void> init() async { _prefs = await SharedPreferences.getInstance(); await loadPreferences(); } // 从SharedPreferences加载数据 Future<void> loadPreferences() async { _page = _prefs.getInt('page') ?? 150; _visible = _prefs.getBool('visible') ?? false; _font = _prefs.getDouble('font') ?? 40; // 还原文本对齐方式 final alignStr = _prefs.getString('align') ?? 'center'; align = _parseTextAlign(alignStr); // 还原颜色(Colors.red[200]的十六进制值为FFf8b1b1) final colorStr = _prefs.getString('selectionColor') ?? 'FFF8B1B1'; selection = _parseColor(colorStr); notifyListeners(); } // TextAlign转字符串存储 String _textAlignToString(TextAlign align) { switch (align) { case TextAlign.left: return 'left'; case TextAlign.right: return 'right'; default: return 'center'; } } // 字符串还原TextAlign TextAlign _parseTextAlign(String str) { switch (str) { case 'left': return TextAlign.left; case 'right': return TextAlign.right; default: return TextAlign.center; } } // Color转十六进制字符串存储 String _colorToString(Color color) { return color.value.toRadixString(16).padLeft(8, '0').toUpperCase(); } // 十六进制字符串还原Color Color _parseColor(String str) { return Color(int.parse(str, radix: 16)); } // 保存配置到SharedPreferences Future<void> _savePreferences() async { await _prefs.setInt('page', _page); await _prefs.setBool('visible', _visible); await _prefs.setDouble('font', _font); await _prefs.setString('align', _textAlignToString(align)); await _prefs.setString('selectionColor', _colorToString(selection)); } // 修改对齐方式并保存 change_align_left() { align = TextAlign.left; _savePreferences(); notifyListeners(); } change_align_center() { align = TextAlign.center; _savePreferences(); notifyListeners(); } change_align_right() { align = TextAlign.right; _savePreferences(); notifyListeners(); } // 修改颜色并保存 change_color_1() { selection = Colors.green[200]!; _savePreferences(); notifyListeners(); } change_color_2() { selection = Colors.blue[200]!; _savePreferences(); notifyListeners(); } change_color_3() { selection = Colors.deepOrange[200]!; _savePreferences(); notifyListeners(); } change_color_4() { selection = Colors.pink[200]!; _savePreferences(); notifyListeners(); } change_color_5() { selection = Colors.red[200]!; _savePreferences(); notifyListeners(); } change_color_6() { selection = Colors.brown[200]!; _savePreferences(); notifyListeners(); } change_color_7() { selection = Colors.deepPurple[200]!; _savePreferences(); notifyListeners(); } // 修改字体大小并保存 change_font_1() async { _font = 30; await _savePreferences(); notifyListeners(); } change_font_2() async { _font = 35; await _savePreferences(); notifyListeners(); } change_font_3() async { _font = 40; await _savePreferences(); notifyListeners(); } copy_on() { _visible = !_visible; _savePreferences(); notifyListeners(); } page_down() { if (_page > 0) { _page--; _savePreferences(); notifyListeners(); } } page_up() { if (_page < 152) { _page++; _savePreferences(); notifyListeners(); } } }
2. 应用启动时初始化CountPage
需在main函数中先加载持久化配置,再将CountPage注入Provider:
void main() async { WidgetsFlutterBinding.ensureInitialized(); final countPage = CountPage(); await countPage.init(); // 先加载保存的配置 runApp( ChangeNotifierProvider.value( value: countPage, child: const MyApp(), ), ); }
3. 修复Option_pageState的代码问题
原代码中initState写在了build方法内部,需移至外部:
class _Option_pageState extends State<Option_page> { @override void initState() { super.initState(); // 配置已在main中初始化,无需额外操作 } @override Widget build(BuildContext context) { final countPage = Provider.of<CountPage>(context); return Scaffold( appBar: AppBar( backgroundColor: countPage.selection, centerTitle: true, title: const Text("설정"), ), body: Center( child: Container( child: Column(children: [ Text( "글자 크기 ", style: TextStyle( fontSize: countPage.font, ), ), Container( height: 50, child: Row( children: [ const Container(child: Text('글자크기')), Container( width: 300, color: Colors.green[200], child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ IconButton( onPressed: countPage.change_font_1, icon: const Icon(Icons.looks_one_outlined)), IconButton( onPressed: countPage.change_font_2, icon: const Icon(Icons.looks_two_outlined)), IconButton( onPressed: countPage.change_font_3, icon: const Icon(Icons.looks_3_outlined)), ], ), ) ], ), ), Container( color: countPage.selection, height: 50, child: Row( children: [ TextButton( onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const Color_choic())); }, child: const Text("색깔변경 "), style: TextButton.styleFrom(primary: Colors.white), ), ], ), ), Container( color: Colors.white, height: 50, child: Row( children: [ const Text('글자정렬'), Container( width: 300, color: Colors.lightGreen, child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ IconButton( onPressed: countPage.change_align_left, icon: const Icon(Icons.format_align_left)), IconButton( onPressed: countPage.change_align_center, icon: const Icon(Icons.format_align_center)), IconButton( onPressed: countPage.change_align_right, icon: const Icon(Icons.format_align_right)), ], ), ), ], ), ), ]), ), ), ); } }
关键说明
- 数据转换:
TextAlign通过字符串标识转换,Color通过十六进制字符串转换,适配SharedPreferences的存储限制 - 初始化时机:必须在应用启动时先加载持久化数据,确保界面启动时显示保存后的配置
- 自动保存:每个状态修改方法调用后执行
_savePreferences(),保证修改立即持久化
内容的提问来源于stack exchange,提问作者GodHanmin
相关产品推荐
相关产品推荐

