GetStorage Patterns
GetStorage Patterns
Initialization
// main.dart
void main() async {
await GetStorage.init();
runApp(MyApp());
}
Storage Service Pattern
class StorageService {
final GetStorage _box;
StorageService() : _box = GetStorage();
// Token management
String? get token => _box.read<String>('auth_token');
Future<void> setToken(String token) => _box.write('auth_token', token);
Future<void> clearToken() => _box.remove('auth_token');
// User data
Map<String, dynamic>? get userData => _box.read<Map<String, dynamic>>('user_data');
Future<void> setUserData(Map<String, dynamic> data) => _box.write('user_data', data);
// Preferences
bool get isDarkMode => _box.read<bool>('dark_mode') ?? false;
Future<void> setDarkMode(bool value) => _box.write('dark_mode', value);
String get locale => _box.read<String>('locale') ?? 'en';
Future<void> setLocale(String locale) => _box.write('locale', locale);
// Clear all
Future<void> clearAll() => _box.erase();
// Listen to changes
void listenKey(String key, Function(dynamic) callback) {
_box.listenKey(key, callback);
}
}
Local Data Source Pattern
class UserLocalDataSource {
final GetStorage _storage;
static const String _usersKey = 'cached_users';
static const String _userKeyPrefix = 'cached_user_';
static const Duration _cacheDuration = Duration(hours: 24);
UserLocalDataSource(this._storage);
Future<void> cacheUser(UserModel user) async {
final cacheData = {
'user': user.toJson(),
'timestamp': DateTime.now().toIso8601String(),
};
await _storage.write('$_userKeyPrefix${user.id}', cacheData);
}
Future<UserModel?> getCachedUser(String id) async {
final cacheData = _storage.read<Map<String, dynamic>>('$_userKeyPrefix$id');
if (cacheData == null) return null;
// Check cache expiration
final timestamp = DateTime.parse(cacheData['timestamp']);
if (DateTime.now().difference(timestamp) > _cacheDuration) {
await _storage.remove('$_userKeyPrefix$id');
return null;
}
return UserModel.fromJson(cacheData['user']);
}
Future<void> cacheUsers(List<UserModel> users) async {
final cacheData = {
'users': users.map((u) => u.toJson()).toList(),
'timestamp': DateTime.now().toIso8601String(),
};
await _storage.write(_usersKey, cacheData);
}
Future<List<UserModel>?> getCachedUsers() async {
final cacheData = _storage.read<Map<String, dynamic>>(_usersKey);
if (cacheData == null) return null;
final timestamp = DateTime.parse(cacheData['timestamp']);
if (DateTime.now().difference(timestamp) > _cacheDuration) {
await _storage.remove(_usersKey);
return null;
}
final List<dynamic> usersList = cacheData['users'];
return usersList.map((json) => UserModel.fromJson(json)).toList();
}
Future<void> clearCache() async {
await _storage.erase();
}
}
GetX Service Integration
class CacheService extends GetxService {
final GetStorage _storage;
CacheService() : _storage = GetStorage();
Future<CacheService> init() async {
await GetStorage.init();
return this;
}
// Reactive cache
final _cachedData = <String, dynamic>{}.obs;
T? get<T>(String key) {
return _storage.read<T>(key);
}
Future<void> put<T>(String key, T value, {Duration? expiry}) async {
if (expiry != null) {
final expiryData = {
'value': value,
'expiry': DateTime.now().add(expiry).toIso8601String(),
};
await _storage.write(key, expiryData);
} else {
await _storage.write(key, value);
}
_cachedData[key] = value;
}
Future<void> remove(String key) async {
await _storage.remove(key);
_cachedData.remove(key);
}
bool has(String key) {
return _storage.hasData(key);
}
}
Best Practices
- Initialize GetStorage before running app
- Use type-safe reads (
read<String>,read<int>, etc.) - Implement cache expiration for time-sensitive data
- Clear cache on logout
- Use separate keys for different data types
- Listen to changes for reactive updates
More from kaakati/rails-enterprise-dev
flutter conventions & best practices
Dart 3.x and Flutter 3.x conventions, naming patterns, code organization, null safety, and async/await best practices
55getx state management patterns
GetX controllers, reactive state, dependency injection, bindings, navigation, and best practices
52tailadmin ui patterns
TailAdmin dashboard UI framework patterns and Tailwind CSS classes. ALWAYS use this skill when: (1) Building any dashboard or admin panel interface, (2) Creating data tables, cards, charts, or metrics displays, (3) Implementing forms, buttons, alerts, or modals, (4) Building navigation (sidebar, header, breadcrumbs), (5) Any UI work that should follow TailAdmin design. This skill REQUIRES fetching from the official GitHub repository to ensure accurate class usage - NEVER invent classes.
39mvvm-architecture
Expert MVVM decisions for iOS/tvOS: choosing between ViewModel patterns (state enum vs published properties vs Combine), service layer boundaries, dependency injection strategies, and testing approaches. Use when designing ViewModel architecture, debugging data flow issues, or deciding where business logic belongs. Trigger keywords: MVVM, ViewModel, ObservableObject, @StateObject, service layer, dependency injection, unit test, mock, architecture
36rails localization (i18n) - english & arabic
Comprehensive internationalization skill for Ruby on Rails applications with proper English and Arabic translations, RTL support, pluralization rules, date/time formatting, and culturally appropriate content adaptation.
34rspec testing patterns
Complete guide to testing Ruby on Rails applications with RSpec. Use this skill when writing unit tests, integration tests, system tests, or when setting up test infrastructure including factories, shared examples, and mocking strategies.
31