使用ThemProvider切换主题会导致小部件重置其状态



我正在开发一个小型测试应用程序,我想添加一个开关来切换亮/暗模式。

我一直在学习这个教程,但问题是:

当我点击开关来更改主题时,整个小部件都会重新生成(我已经打印了哈希,每次切换开关时它们都不一样(,以及它的状态和变量。但由于在该页面中,我加载了一些资源并更新了小部件组件(例如,我从文件中加载了测验问题,并更新了一些文本,说明有多少问题(,这些都会被重置。问题是我只想改变主题,让小部件及其变量保持原样,但我找不到任何解决方案/解决方法或解释为什么会发生这种情况。

以下是发生的事情的gif图:调试测试

这些是涉及的文件和类:

main.dart

void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (context) => ThemeProvider(),
builder: (context, _) {
final themeProvider = Provider.of<ThemeProvider>(context);
return MaterialApp(
title: 'ROquiz',
themeMode: themeProvider.themeMode,
theme: MyThemes.themeLight,
darkTheme: MyThemes.themeDark,
home: ViewMenu(),
);
});
}

主题.省道

class ThemeProvider extends ChangeNotifier {
ThemeMode themeMode = ThemeMode.light;
bool get isDarkMode => themeMode == ThemeMode.dark;
void toggleTheme(bool isOn) {
themeMode = isOn ? ThemeMode.dark : ThemeMode.light;
notifyListeners();
}
}
class MyThemes {
static final themeLight = ThemeData(
colorSchemeSeed: Colors.blue,
brightness: Brightness.light,
//iconTheme: IconThemeData(color: Colors.blue[900]),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
)))),
);
static final themeDark = ThemeData(
scaffoldBackgroundColor: Colors.indigo[700],
brightness: Brightness.dark,
colorScheme: const ColorScheme.dark(),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Colors.blue))))));
}

change_theme_button_widget.dart

class ChangeThemeButtonWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);
return Switch.adaptive(
value: themeProvider.isDarkMode,
onChanged: (value) {
final provider = Provider.of<ThemeProvider>(context, listen: false);
provider.toggleTheme(value);
});
}
}

查看菜单.dart

class ViewMenu extends StatefulWidget {
// [...]
}
class ViewMenuState extends State<ViewMenu> {
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);

return Scaffold(
// [...]
ChangeThemeButtonWidget(),
// [...]
);
}
}

我认为解决方案之一是将进度存储在本地存储中。您可以使用共享首选项https://pub.dev/packages/shared_preferences

我找到了解决方案,并将其发布在那里,因为我认为它可能对其他人有用。

我做错的是,我使用小部件来存储一些状态(并使用widget.访问它(。因此,每次我使用开关更改主题时,都会重新构建小部件及其内部变量(即状态(。相反,通过将每个变量移动到状态类,它工作得很好,并且在切换时状态保持不变

类ViewMenu

class ViewMenu extends StatefulWidget {
ViewMenu({Key? key}) : super(key: key);

// I hasome state there
@override
State<StatefulWidget> createState() => ViewMenuState();
}

类ViewMenuState

class ViewMenuState extends State<ViewMenu> {
// The state should be all there for the theme changer to work properly
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);

return Scaffold(
// [...]
ChangeThemeButtonWidget(),
// [...]
);
}
}

看来,使用ThemeProvider,flutter重建小部件,但不重建其状态,因此,为了使其工作,使用StatefulWidget,您必须将所有内容存储在扩展state的类中。

相关内容

  • 没有找到相关文章

最新更新