Search code examples
flutterprovider

How do I use Provider between Widgets?


I'm facing an annoying problem about the Provider package. I want to implement the night mode switch. I've tried to use the Provider in a separate screen and it works, but obv where I would need him, it doesn't :)

My theme class

class MyTheme {

  static ThemeData lightTheme = ThemeData(
    //something very nice
  );

  static ThemeData nightTheme = ThemeData(
    //something very nice
  );
}

My root page

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @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(),
          );
        });
  }
}

My homePage (where there is the button used for changing the mode)

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:

The MyAppDrawer widget

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,
                    ),
                  ),
                ],
              ),
            ),

The Provider Class

class ThemeProvider extends ChangeNotifier {
  ThemeData _themeData = MyTheme.lightTheme;
  ThemeData get themeData => _themeData;

  void toggleTheme() {
    debugPrint('Siamo entrati nel toggle');
    final isLight = _themeData == MyTheme.lightTheme;
    isLight ? _themeData = MyTheme.nightTheme : _themeData = MyTheme.lightTheme;
    notifyListeners();
  }
}

I've tried the debugging mode and got that it doesn't even enter the toggleTheme() method (the one in the Provider class). I really don't know why.


Solution

  • The main issue seems to be in the MyAppDrawer widget where you are referencing the method without actuall calling it provider.toggleTheme instead it should be provider.toggleTheme();