shared_prefs_typed 0.5.0 copy "shared_prefs_typed: ^0.5.0" to clipboard
shared_prefs_typed: ^0.5.0 copied to clipboard

Code generator for creating type-safe, boilerplate-free SharedPreferences classes in Dart & Flutter.

example/main.dart

// ignore_for_file: unused_element, unused_field // This file is used for code generation and may contain unused elements or fields.

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

// This file is generated by the code generator.
import 'theme_example.g.dart';

/// Defines the data contract for the application's settings preferences.
@TypedPrefs()
abstract class _SettingsPrefs {
  /// This preference is stored as a nullable boolean with the following mapping:
  /// - `true`:  ThemeMode.light
  /// - `false`: ThemeMode.dark
  /// - `null`:  ThemeMode.system (this is the default value)
  static const bool? isLight = null;
}

/// The main entry point for the application.
Future<void> main() async {
  // Required to ensure that plugin services are initialized before `runApp`.
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize our preferences service. This must be done once on startup.
  // After this `await`, `SettingsPrefs.instance` is available for use.
  await SettingsPrefs.init();

  runApp(const MyApp());
}

// --- 3. Root Widget and State Management ---

/// The root widget of the application.
///
/// This is a [StatefulWidget] because it holds and manages the application's
/// current [ThemeMode]. When the user changes the theme, this widget rebuilds
/// the [MaterialApp] with the new theme setting.
class MyApp extends StatefulWidget {
  /// Creates the root application widget.
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // The state variable that holds the current theme for the UI.
  // It is initialized in `initState` to avoid using `late`.
  late ThemeMode _themeMode;

  @override
  void initState() {
    super.initState();
    // On startup, read the saved preference and set the initial theme.
    // We can safely access the singleton instance because `init()` was called in `main`.
    final isLight = SettingsPrefs.instance.isLight;
    _themeMode = _getThemeModeFromPreference(isLight);
  }

  /// Converts the stored preference (`bool?`) into a Flutter [ThemeMode].
  ThemeMode _getThemeModeFromPreference(bool? isLight) {
    switch (isLight) {
      case true:
        return ThemeMode.light;
      case false:
        return ThemeMode.dark;
      case null:
        return ThemeMode.system;
    }
  }

  /// Updates the theme, persists the choice, and rebuilds the UI.
  ///
  /// This method is passed as a callback to child widgets, allowing them
  /// to trigger a state change in this root widget.
  Future<void> _changeTheme(bool? newIsLightPreference) async {
    // 1. Persist the new choice to SharedPreferences using the generated setter.
    await SettingsPrefs.instance.setIsLight(newIsLightPreference);

    // 2. Update the local state to trigger a UI rebuild with the new theme.
    setState(() {
      _themeMode = _getThemeModeFromPreference(newIsLightPreference);
    });
  }

  @override
  Widget build(BuildContext context) {
    // We get the current preference value here to pass it down to the UI.
    final currentPreference = SettingsPrefs.instance.isLight;

    return MaterialApp(
      title: 'Simple Theme Demo',
      // Define both a light and a dark theme for the app.
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      // Use the state variable to control which theme is currently active.
      themeMode: _themeMode,
      home: MyHomePage(
        // Pass the current state and the change handler down to the UI.
        currentPreference: currentPreference,
        onThemeChanged: _changeTheme,
      ),
    );
  }
}

// --- 4. UI Screen Widget ---

/// The home page of the application, responsible for displaying the UI.
///
/// This is a [StatelessWidget] because it does not manage its own state.
/// It receives its data (`currentPreference`) and behavior (`onThemeChanged`)
/// from its parent widget. This separation makes the UI component clean and reusable.
class MyHomePage extends StatelessWidget {
  /// Creates the home page widget.
  const MyHomePage({
    required this.currentPreference,
    required this.onThemeChanged,
    super.key,
  });

  /// The currently selected theme preference (`true`, `false`, or `null`).
  final bool? currentPreference;

  /// A callback function to notify the parent widget of a theme change.
  final ValueChanged<bool?> onThemeChanged;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Theme Selector'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'Choose your theme:',
              style: TextStyle(fontSize: 18),
            ),
            const SizedBox(height: 20),
            SegmentedButton<bool?>(
              segments: const [
                ButtonSegment(
                  value: null, // System
                  label: Text('System'),
                  icon: Icon(Icons.brightness_auto),
                ),
                ButtonSegment(
                  value: true, // Light
                  label: Text('Light'),
                  icon: Icon(Icons.wb_sunny),
                ),
                ButtonSegment(
                  value: false, // Dark
                  label: Text('Dark'),
                  icon: Icon(Icons.nightlight_round),
                ),
              ],
              // The `selected` property expects a Set of the selected values.
              selected: {currentPreference},
              // When the user makes a new selection, the new value is
              // provided in a Set. We extract the first (and only) value
              // and call the `onThemeChanged` callback to notify the parent.
              onSelectionChanged: (newSelection) {
                onThemeChanged(newSelection.first);
              },
            ),
          ],
        ),
      ),
    );
  }
}
2
likes
0
points
68
downloads

Publisher

verified publisherphilippgerber.li

Weekly Downloads

Code generator for creating type-safe, boilerplate-free SharedPreferences classes in Dart & Flutter.

Repository (GitHub)
View/report issues

Topics

#shared-preferences #persistence #codegen #type-safe

License

unknown (license)

Dependencies

analyzer, build, build_config, code_builder, dart_style, meta, pub_semver, shared_prefs_typed_annotations, source_gen

More

Packages that depend on shared_prefs_typed