Modo oscuro y claro en Flutter utilizando Riverpod
Tags: flutter, mobile, riverpod, dart
Published: 2023-11-18 23:34:50

Siguiendo con el articulo anterior [Modo oscuro y claro en Flutter utilizando GetX](https://dev.to/rubone/modo-oscuro-y-claro-en-flutter-utilizando-getx-3fd4), ahora realizaremos la misma aplicación pero utilizando [Riverpod](https://riverpod.dev/). Riverpod es un paquete para gestión de estado, ayuda a organizar y gestionar la información que se utiliza en la aplicación de manera eficiente. Proporciona un enfoque más declarativo y modular para la gestión del estado en comparación con otras soluciones.

Para este ejemplo utilizaremos [Riverpod Hooks](https://pub.dev/packages/hooks_riverpod), que es una extensión de Riverpod que proporciona hooks para trabajar con el paquete Riverpod en aplicaciones Flutter.

## Creando nuestro proyecto
Para crear el proyecto ejecuta el siguiente comando:

```
flutter create riverpod_theme
```
Luego agregamos el paquete de Riverpod hooks al proyecto en nuestro archivo pubspec.yaml.

```
hooks_riverpod: ^2.4.4
```
Y por último ejecutamos el comando `pub get` para obtener los paquetes en nuestro proyecto.

```
flutter pub get
```

## Creando nuestro tema
Primero crearemos nuestro archivo `theme.dart` donde tendremos definidos nuestro modo claro y oscuro.

```
import 'package:flutter/material.dart';

final ThemeData darkAppTheme = ThemeData(
  brightness: Brightness.dark,
  primaryColor: Colors.amber,
  buttonTheme: const ButtonThemeData(
    buttonColor: Colors.amber,
    disabledColor: Colors.grey,
  ),
);

final ThemeData lightAppTheme = ThemeData(
  brightness: Brightness.light,
  primaryColor: Colors.blue,
  buttonTheme: const ButtonThemeData(
    buttonColor: Colors.blue,
    disabledColor: Colors.grey,
  ),
);
```

Utilizando Riverpod crearemos una clase provider para el manejo de estado de nuestro tema dentro de la aplicación. Crearemos el archivo `themes_provider.dart` y agregaremos el siguiente código:

```
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

final themesProvider = StateNotifierProvider<ThemesProvider, ThemeMode>((ref) {
  return ThemesProvider();
});

class ThemesProvider extends StateNotifier<ThemeMode> {
  ThemesProvider() : super(ThemeMode.system);

  void changeTheme(bool isOn) {
    state = isOn ? ThemeMode.dark : ThemeMode.light;
  }
}
```

## Utilizando nuestro tema
Para utilizar nuestro tema crearemos una pantalla que será nuestro Home donde agregaremos un action en nuestro AppBar para establecer el tema de la aplicación.

En nuestra pantalla de Home utilizaremos `ConsumerWidget` para estar a la escucha de los cambios generados en nuestra clase provider creada para manejar el estado de de nuestra tema.  Crearemos el archivo `home.dart` y agregaremos el siguiente código:

```
class HomeScreen extends ConsumerWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final themeModeState = ref.watch(themesProvider);
    return Scaffold(
      appBar: AppBar(
        title: const Text('Riverpod Theme'),
        actions: [
          IconButton(
              icon: Icon(
                themeModeState == ThemeMode.light
                    ? Icons.dark_mode
                    : Icons.light_mode,
              ),
              onPressed: () => ref.read(themesProvider.notifier).changeTheme(
                  themeModeState == ThemeMode.light ? true : false)),
        ],
      ),
    );
  }
}
```

Finalmente en nuestro archivo `main.dart` utilizaremos `ProviderScope` de Riverpod para nuestro Widget principal. Adicionalmente estableceremos los valores para theme y darkTheme utilizando las configuraciones de los temas que agregamos en nuestro archivo `theme.dart`

```
void main() {
  runApp(
    const ProviderScope(child: MyApp()),
  );
}

class MyApp extends ConsumerWidget {
  const MyApp({
    super.key,
  });
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final themeModeState = ref.watch(themesProvider);
    return MaterialApp(
      theme: lightAppTheme,
      darkTheme: darkAppTheme,
      themeMode: themeModeState,
      debugShowCheckedModeBanner: false,
      home: const HomeScreen(),
    );
  }
}
```

## Ejecutando nuestra aplicación
Utiliza el siguiente comando para correr la aplicación y puedas ver todo nuestro código en acción.

```
flutter run
```

## Conclusiones
Implementar el modo oscuro y modo claro en nuestras aplicaciones puede mejorar la experiencia del usuario al brindarles opciones de personalización y adaptabilidad. Con Riverpod puedes implementar dicha funcionalidad de una forma sencilla y robusta. 

Puedes revisar el código en [GitHub](https://github.com/rubone/riverpod_theme)

Happy Coding! ✌️