扩展ChangeNotifier类中的Init值



我是新来的扑动,我一直在努力做一个非常基本的例子:在运行时从黑暗到明亮改变主题。

到目前为止,它使用ChangeNotifier工作,但现在我想在启动时初始化我的_isDarkMode变量,通过使用SharedPreferences

我的解决方案感觉像一个hack,是完全错误的:它似乎从首选项加载,但最终的结果是总是黑暗的模式。

这就是我所做的。首先,我用init函数修改了这个类,并添加了对SharedPreferences的必要调用:

class PreferencesModel extends ChangeNotifier {
static const _darkModeSetting = "darkmode";
bool _isDarkMode = true; // default, overridden by init()
bool get isDarkMode => _isDarkMode;
ThemeData get appTheme => _isDarkMode ? AppThemes.darkTheme : AppThemes.lightTheme;
void init() async {
final prefs = await SharedPreferences.getInstance();
final bool? dark = prefs.getBool(_darkModeSetting);
_isDarkMode = dark ?? false;
await prefs.setBool(_darkModeSetting, _isDarkMode);
}
void setDarkMode(bool isDark) async {
print("setting preferences dark mode to ${isDark}");
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_darkModeSetting, isDark);
_isDarkMode = isDark;
notifyListeners();
}
}

然后,在main中,我从ChangeNotifierProvidercreatelambda调用init:

void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) {
var prefs = PreferencesModel();
prefs.init(); // overrides dark mode
return prefs;
})
],
child: const MyApp(),
)
);
}

创建MaterialAppState基于首选项初始化ThemeMode:

class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return Consumer<PreferencesModel>(
builder: (context, preferences, child) {
return MaterialApp(
title: 'MyApp',
home: MainPage(title: 'MyApp'),
theme: AppThemes.lightTheme,
darkTheme: AppThemes.darkTheme,
themeMode: preferences.isDarkMode ? ThemeMode.dark : ThemeMode.light,
);
}
);
}
}

当然,如果我改变设置页面中的设置(在ToggleButton处理程序上使用preferences.setDarkMode(index == 1);),它可以工作,在运行时从亮到暗再变回来。初始化是完全错误的。

我在这里错过了什么?

我破例地回答了自己的问题。

解决方案是将首选项读取移动到主,将main改为async

首先,PreferencesModel应该有一个设置初始暗模式的构造函数:

class PreferencesModel extends ChangeNotifier {
static const darkModeSetting = "darkmode";
PreferencesModel(bool dark) {
_isDarkMode = dark;
}
bool _isDarkMode = true;
// ...

main功能可以为async,正确使用共享首选项,将暗模式传递给PreferencesModel:

void main() async {
WidgetsFlutterBinding.ensureInitialized();
final prefs = await SharedPreferences.getInstance();
final bool dark = prefs.getBool(PreferencesModel.darkModeSetting) ?? false;
print("main found dark as ${dark}");
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => PreferencesModel(dark))
],
child: const RecallableApp(),
)
);
}

请注意WidgetsFlutterBinding.ensureInitialized();调用,否则共享首选项将不起作用,应用程序崩溃。

最新更新