Flutter中结合Change Notifier使用Shared Preferences的问题求助
我正在学习如何在Flutter中结合Change Notifier使用Shared Preferences,已创建一个基础应用,希望通过Shared Preferences保存Change Notifier中的bool类型值和string类型值。
main.dart 代码
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => GlobalSettings1()), ChangeNotifierProvider(create: (_) => SectionSettings1()), ], child: MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, initialRoute: '/seventh', routes: { '/': (context) => Page01(), '/first': (context) => Page02(), '/second': (context) => Page03(), }); } }
Page01 代码
class _Page01State extends State<Page01> { @override Widget build(BuildContext context) { return Scaffold( body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ InkWell( onTap: () { context.read<GlobalSettings1>().ToggleSwitch(); }, child: Container( height: 30, width: 80, color: context.watch<GlobalSettings1>().toggleSwitch01 ? Colors.green : Colors.red, ), ), SizedBox( height: 20, ), InkWell( onTap: () { showDialog( context: context, builder: (BuildContext context) => Material( color: Colors.transparent, child: Buttons( onTap: (val) { context.read<GlobalSettings1>().StringToSave(val); Navigator.pop(context); }, ), ), ); }, child: Container( height: 30, width: 80, child: Center( child: Text( context.watch()<GlobalSettings1>().stringToSave, ), ), )), ], ), ); } }
Change Notifier 代码
class Buttons extends StatelessWidget { const Buttons({Key? key, required this.onTap}) : super(key: key); final ValueChanged? onTap; @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ InkWell( onTap: () { if (onTap != null) { onTap!('Choice01'); } }, child: Container( height: 30, width: 80, child: Text('Choice01'), )), SizedBox( height: 30, ), InkWell( onTap: () { if (onTap != null) { onTap!('Choice02'); } }, child: Container( height: 30, width: 80, child: Text('Choice02'), )), ], ); } } class GlobalSettings1 with ChangeNotifier { bool _toggleSwitch01 = true; String _stringToSave = 'Choice01'; final SharedPreferences prefs; GlobalSettings1({required this.prefs}); bool get toggleSwitch01 => _toggleSwitch01; String get stringToSave => _stringToSave; void ToggleSwitch() { _toggleSwitch01 = !_toggleSwitch01; _setPrefItems(); notifyListeners(); } void StringToSave(val) { _stringToSave = val; _setPrefItems(); notifyListeners(); } void _setPrefItems() { prefs.setBool('toggleSwitch01', _toggleSwitch01); prefs.setString('stringToSave', _stringToSave); notifyListeners(); } void _getPrefItems() async { SharedPreferences prefs = await SharedPreferences.getInstance(); _stringToSave = prefs.getString('stringToSave') ?? ''; _toggleSwitch01 = prefs.getBool('autoUpdateVariables') ?? true; notifyListeners(); } bool getToggleSwitch01() { _getPrefItems(); return _toggleSwitch01; } String getStringToSave() { _getPrefItems(); return _stringToSave; } }
核心问题
main.dart中ChangeNotifierProvider(create: (_) => GlobalSettings1())提示需要必填参数prefs,不知道该如何传入;- 不确定如何配置
main.dart和Page01,使得APP重启后,之前设置的bool值和string值能保持。
解决方案
1. 修改main函数,异步初始化SharedPreferences
SharedPreferences.getInstance()是异步操作,需要先完成初始化再启动App,修改main.dart的main函数:
void main() async { WidgetsFlutterBinding.ensureInitialized(); // 确保Flutter绑定初始化 final prefs = await SharedPreferences.getInstance(); runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => GlobalSettings1(prefs: prefs)), ChangeNotifierProvider(create: (_) => SectionSettings1()), ], child: MyApp(), ), ); }
2. 修正GlobalSettings1的状态加载逻辑
当前_getPrefItems存在重复获取实例、键名错误的问题,同时需要在构造函数中自动加载保存的状态:
class GlobalSettings1 with ChangeNotifier { bool _toggleSwitch01 = true; String _stringToSave = 'Choice01'; final SharedPreferences prefs; // 构造函数中自动加载保存的配置 GlobalSettings1({required this.prefs}) { _loadPrefs(); } bool get toggleSwitch01 => _toggleSwitch01; String get stringToSave => _stringToSave; void ToggleSwitch() { _toggleSwitch01 = !_toggleSwitch01; _savePrefs(); notifyListeners(); } void StringToSave(String val) { _stringToSave = val; _savePrefs(); notifyListeners(); } // 保存配置到SharedPreferences void _savePrefs() { prefs.setBool('toggleSwitch01', _toggleSwitch01); prefs.setString('stringToSave', _stringToSave); } // 加载保存的配置 void _loadPrefs() { _stringToSave = prefs.getString('stringToSave') ?? 'Choice01'; _toggleSwitch01 = prefs.getBool('toggleSwitch01') ?? true; // 修正键名错误 notifyListeners(); } // 移除冗余的getToggleSwitch01和getStringToSave方法,直接通过getter获取状态 }
3. 修复Page01中的语法错误
Page01中Text组件的context.watch()写法错误,修正为:
child: Text( context.watch<GlobalSettings1>().stringToSave, ),
内容的提问来源于stack exchange,提问作者Nomad09
相关产品推荐
相关产品推荐

