App Storage
A simple and secure local storage package with support for primitives, collections, and JSON serialization.

A simple and secure local storage package with support for primitives, collections, JSON serialization, and secure data storage.
Features#
- Simple API - Easy-to-use interface for all storage operations
- Type Safety - Generic methods with compile-time type checking
- Multiple Data Types - Support for primitives, lists, maps, and custom objects
- Secure Storage - Encrypted storage for sensitive data (tokens, passwords)
- TTL Support - Time-to-live for cached data
- Singleton Pattern - Easy access from anywhere in your app
- Exception Handling - Proper error handling with custom exceptions
- JSON Serialization - Automatic serialization for complex types
Installation#
Add this to your pubspec.yaml:
dependencies:
app_storage: ^1.0.0Then run:
flutter pub getQuick Start#
Initialize Storage#
import 'package:app_storage/app_storage.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize storage service
await StorageService.instance.init();
runApp(MyApp());
}Basic Usage#
final storage = StorageService.instance;
// Save data
await storage.save('user_id', '12345');
await storage.save('age', 25);
await storage.save('is_active', true);
// Retrieve data
final userId = await storage.get<String>('user_id');
final age = await storage.get<int>('age');
final isActive = await storage.get<bool>('is_active');
// Delete data
await storage.delete('user_id');
// Clear all data
await storage.clear();Supported Data Types#
Primitives#
await storage.save('name', 'John Doe'); // String
await storage.save('age', 25); // int
await storage.save('height', 5.9); // double
await storage.save('is_enrolled', true); // boolLists#
await storage.save('subjects', ['Math', 'Science', 'English']);
await storage.save('grades', [85, 92, 78, 95]);
final subjects = await storage.get<List<String>>('subjects');
final grades = await storage.get<List<int>>('grades');Maps (JSON)#
await storage.save('user_data', {
'name': 'John Doe',
'email': 'john@example.com',
'role': 'student',
'enrolled': true,
});
final userData = await storage.get<Map<String, dynamic>>('user_data');Complex Objects#
final student = {
'id': 'STU001',
'name': 'Alice Smith',
'grade': 10,
'subjects': ['Math', 'Physics', 'Chemistry'],
'scores': {
'Math': 95,
'Physics': 88,
'Chemistry': 92,
}
};
await storage.save('student_profile', student);
final profile = await storage.get<Map<String, dynamic>>('student_profile');Secure Storage#
For sensitive data like authentication tokens, passwords, and API keys:
final secureStorage = SecureStorageService.instance;
// Save sensitive data
await secureStorage.save('auth_token', 'jwt_token_here');
await secureStorage.save('api_key', 'sk_live_1234567890');
await secureStorage.save('password', 'MySecureP@ssw0rd');
// Retrieve sensitive data
final authToken = await secureStorage.get<String>('auth_token');
final apiKey = await secureStorage.get<String>('api_key');
// All other methods work the same way
await secureStorage.delete('auth_token');
await secureStorage.clear();Time-To-Live (TTL)#
Cache data with automatic expiration:
// Save with 1 hour TTL (3600 seconds)
await storage.save('session_data', sessionInfo, ttl: 3600);
// Save with 5 minute TTL
await storage.save('temp_token', token, ttl: 300);
// Data automatically expires and returns null after TTL
final data = await storage.get<String>('session_data'); // null after 1 hourUtility Methods#
Check Key Existence#
final exists = await storage.containsKey('user_id');
if (exists) {
// Key exists
}Get All Keys#
final keys = await storage.getKeys();
print('Stored keys: $keys');Get All Data#
final allData = await storage.getAll();
allData.forEach((key, value) {
print('$key: $value');
});Exception Handling#
The package provides custom exceptions for better error handling:
try {
await storage.save('user_data', complexObject);
} on SerializationException catch (e) {
print('Serialization failed: ${e.message}');
} on TypeMismatchException catch (e) {
print('Type mismatch: expected ${e.expectedType}, got ${e.actualType}');
} on StorageException catch (e) {
print('Storage error: ${e.message}');
}Real-World Examples#
User Authentication#
class AuthService {
final secureStorage = SecureStorageService.instance;
Future<void> saveAuthData(String token, Map<String, dynamic> user) async {
await secureStorage.save('auth_token', token);
await secureStorage.save('user_data', user);
}
Future<bool> isAuthenticated() async {
return await secureStorage.containsKey('auth_token');
}
Future<void> logout() async {
await secureStorage.delete('auth_token');
await secureStorage.delete('user_data');
}
}User Preferences#
class PreferencesService {
final storage = StorageService.instance;
Future<void> saveTheme(String theme) async {
await storage.save('theme', theme);
}
Future<String> getTheme() async {
return await storage.get<String>('theme') ?? 'light';
}
Future<void> saveNotificationSettings(bool enabled) async {
await storage.save('notifications_enabled', enabled);
}
}Caching API Responses#
class ApiService {
final storage = StorageService.instance;
Future<List<dynamic>> getStudents({bool forceRefresh = false}) async {
if (!forceRefresh) {
final cached = await storage.get<List<dynamic>>('students_cache');
if (cached != null) return cached;
}
// Fetch from API
final students = await fetchFromApi();
// Cache for 1 hour
await storage.save('students_cache', students, ttl: 3600);
return students;
}
}Platform Support#
- ✅ Android
- ✅ iOS
- ✅ Web
- ✅ Windows
- ✅ macOS
- ✅ Linux
Note: Secure storage encryption strength varies by platform. iOS and Android provide the strongest encryption using Keychain and Keystore respectively.
Under the Hood#
- Regular Storage: Uses
shared_preferencespackage - Secure Storage: Uses
flutter_secure_storagepackage with platform-specific encryption- iOS: Keychain
- Android: EncryptedSharedPreferences
- Other platforms: Best available encryption
Best Practices#
- Always initialize storage in
main()before using - Use secure storage for sensitive data (tokens, passwords, API keys)
- Use TTL for cached data to avoid stale information
- Handle exceptions properly in production code
- Don't store large binary data - use file storage instead
- Use type parameters for type safety:
get<String>(),get<int>()
License#
MIT License - feel free to use in your projects
Contributing#
Contributions are welcome! Please open an issue or submit a pull request.
Support#
For issues, questions, or suggestions, please open an issue on GitHub.
Related Projects

App Permissions
Centralized permission management system with automatic requests, status tracking, rationale dialogs, and graceful degradation.

Promo Carousel
A flexible, customizable promotional carousel package for Flutter

App Update Manager
A comprehensive Flutter package for managing app updates across Play Store, App Store, and custom backends with flexible update strategies.