🧩 shared_pref_builder

Generate strongly-typed SharedPreferences accessors in Flutter — without build_runner.

shared_pref_builder lets you define your app preferences as a simple Dart class using annotations,
and automatically generates type-safe, easy-to-use getters and setters.

No build_runner, no boilerplate — just run dart run shared_pref_builder.


🚀 Features

  • No build_runner required — runs instantly via a CLI command.
  • 🧠 Type-safe accessors
    • Primitive types supports int, double, bool, String, List<String>.
    • Type-safe JSON — supports Map<dynamic, dynamic> and List<dynamic>.
    • Type-safe custom conversion — supports custom data model with @SPField(from: , to: ) annotation.
  • ⚙️ Optional configuration in pubspec.yaml for faster, targeted generation.

📦 Installation

dart pub global activate shared_pref_builder

or

Add this to your dev_dependencies in pubspec.yaml

dev_dependencies:
  shared_pref_builder: (latest version)
     

Add the annotation package to your dependencies in pubspec.yaml

dependencies:
  shared_pref_annotation: (latest version)
     

You can specify which file contains your annotated preferences class to improve performance:

shared_pref_builder:
  path: lib/core/app_pref.dart

If path is not provided, the generator will scan all files inside the lib/ directory.


🧠 Usage

1️⃣ Annotate your preferences class

// lib/core/sp.dart

import 'package:shared_preferences/shared_preferences.dart';
import 'package:shared_pref_annotation/shared_pref_annotation.dart';


@SharedPref()
class AppPref {
  String? token;

  /// With default value 
  bool isDarkMode = false;
}

2️⃣ Run the generator

If using as a global dart package, run:

shared_pref_builder

and if using as a dev_dependency, run:

dart run shared_pref_builder

This will generate a file next to your class:



extension AppPrefSpExt on SharedPreferences {
  
  SPValue<String> get token => SPValue<String>(
        key: 'token',
        getter: getString,
        setter: setString,
        remover: remove,
      );

  SPWithDefault<bool> get isDarkMode => SPWithDefault<bool>(
        key: 'isDarkMode',
        getter: getBool,
        setter: setBool,
        remover: remove,
        defaultValue: false,
      );
}

⚡ Use with Custom Data Model class

Your data class

class User {
  const User({required this.name, required this.email});
  final String name;
  final String email;

  Map<String, dynamic> toMap() => {'name': name, 'email': email};

  factory User.fromMap(Map<String, dynamic> map) {
    return User(name: map['name'] ?? '', email: map['email'] ?? '');
  }

  String toJson() => json.encode(toMap());
  factory User.fromJson(String source) => User.fromMap(json.decode(source));

  static String toJsonString(User i) => i.toJson(); // <- custom converter
}

in app_pref.dart

@sharedPref
class AppPref {
  @SPField(from: User.fromJson, to: User.toJsonString)
  User? userData;
}

⚠️ NOTE

  • The method used in from must return the same class and should have only one positional String parameter.
  • The method used in to must return a String and should have only one positional parameter and type of the same class.

🧩 Using Generated Accessors

final prefs = await SharedPreferences.getInstance();

// Read
final token = prefs.token.value;

// Write
await prefs.token.setValue('NEW-TOKEN');

// Remove
await prefs.token.remove();

🧱 Example Project Structure

lib/
 ┣ core/
 ┃ ┗ app_pref.dart
 ┣ main.dart
pubspec.yaml

Generated:

lib/
 ┣ core/
 ┃ ┣ app_pref.dart
 ┃ ┗ app_pref_gen.dart

🙌 Contributing

Fill free to create an issue or open a pull request to contribute.


❤️ Credits

Developed with 💙 by Ahnaf Sakil
Inspired by simplicity — built for real-world Flutter projects.


📄 License

BSD 3-Clause License. See LICENSE for details.