Flutter Provider跨组件使用问题:夜间模式切换无响应
问题:Provider夜间模式切换侧边栏按钮不生效
在使用Provider包实现夜间模式切换时,单独页面使用Provider可正常工作,但侧边栏的切换按钮无法生效,调试发现未进入ThemeProvider的toggleTheme()方法。
相关代码
主题类
class MyTheme { static ThemeData lightTheme = ThemeData( // 自定义浅色主题配置 ); static ThemeData nightTheme = ThemeData( // 自定义深色主题配置 ); }
根页面
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => ThemeProvider(), builder: (context, child) { final provider = Provider.of<ThemeProvider>(context); return MaterialApp( debugShowCheckedModeBanner: true, initialRoute: LoginScreen.id, onGenerateRoute: RouteGenerator.generateRoute, theme: provider.themeData, home: const HomeScreen(), ); }); } }
首页(含侧边栏)
class _HomeScreenState extends State<HomeScreen> { final GlobalKey<ScaffoldState> _globalKey = GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; double width = MediaQuery.of(context).size.width; return Scaffold( key: _globalKey, drawer: MyAppDrawer( height: height, width: width, colore: MyTheme.coloreTesto, ), body: // 页面内容 ); } }
侧边栏组件
class MyAppDrawer extends StatelessWidget { const MyAppDrawer( {super.key, required this.height, required this.width, required this.colore}); final double height; final double width; final Color colore; @override Widget build(BuildContext context) { final provider = Provider.of<ThemeProvider>(context); return Drawer( width: width * 0.7, child: Container( padding: EdgeInsets.only( top: height * 0.1, left: width * 0.08, right: width * 0.08), color: Colors.white, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( margin: EdgeInsets.symmetric(vertical: height * 0.01), child: Row( children: [ Container( child: ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.white), elevation: MaterialStateProperty.all(0.0), padding: MaterialStateProperty.all(EdgeInsets.zero), shape: MaterialStateProperty.all<RoundedRectangleBorder>( RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(width * 0.015))))), onPressed: () { debugPrint('nightModePremuto'); provider.toggleTheme; // 问题所在 }, child: Icon( size: width * 0.06, Icons.dark_mode, color: colore, ), ), ), Text( 'Night Mode', style: TextStyle( color: colore, fontSize: width * 0.04, ), ), ], ), ), ], ), ), ); } }
Provider类
class ThemeProvider extends ChangeNotifier { ThemeData _themeData = MyTheme.lightTheme; ThemeData get themeData => _themeData; void toggleTheme() { debugPrint('Siamo entrati nel toggle'); final isLight = _themeData == MyTheme.lightTheme; _themeData = isLight ? MyTheme.nightTheme : MyTheme.lightTheme; notifyListeners(); } }
解决方案
核心问题修复
你在按钮的onPressed回调中只是引用了方法对象provider.toggleTheme,并没有执行这个方法,必须添加括号才能触发方法调用:
onPressed: () { debugPrint('nightModePremuto'); provider.toggleTheme(); // 添加括号执行方法 },
额外优化建议
减少不必要的组件重建:
获取Provider时添加listen: false,因为侧边栏只需要触发主题切换,不需要监听主题变化来重建自身:final provider = Provider.of<ThemeProvider>(context, listen: false);适配主题的背景色:
侧边栏容器的背景色硬编码为Colors.white,切换夜间模式后不会变化,建议改成使用主题中的颜色:color: Theme.of(context).scaffoldBackgroundColor,
内容的提问来源于stack exchange,提问作者Geremia Moretti
相关产品推荐
相关产品推荐

