> For the complete documentation index, see [llms.txt](https://codesadhu-labs.gitbook.io/normie/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codesadhu-labs.gitbook.io/normie/category-docs/categories/cache.md).

# Cache 🕒

### Overview

~~`Normie.cache` offers a lightweight caching solution that lets you store any type of data with optional expiration times. The cache is memory-based, meaning it persists only during app runtime.~~

`Normie.cache` now offers a lightweight persistent caching solution using SharedPreferences that lets you store any type of data with optional expiration times. The cache persists between app restarts ***(v2.0.1)***.

## Initialization

Before using any cache operations, you must initialize the cache system. This should be done during your app's startup.

```dart
void main() async {
  // Ensure Flutter bindings are initialized
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize the cache
  await Normie.cache.init();
  
  runApp(MyApp());
}
```

Or if using a setup class:

```dart
class AppSetup {
  static Future<void> initialize() async {
    await Normie.cache.init();
    // Other initialization code...
  }
}
```

Note: Attempting to use any cache operations before initialization will throw a `StateError`.

### Available Methods

#### `set`

Stores a value in the cache with an optional expiry duration.

```dart
void set(String key, dynamic value, {Duration? expiry})
```

**Parameters:**

* `key`: String identifier for the cached item
* `value`: Any data you want to store
* `expiry`: Optional Duration after which the item expires

**Example:**

```dart
// Cache for 1 hour
Normie.cache.set('user-preferences', {'theme': 'dark'}, 
  expiry: Duration(hours: 1));

// Cache indefinitely
Normie.cache.set('app-constants', {'apiVersion': '2.0'});
```

#### `get`

Retrieves a value from the cache. Returns null if the key doesn't exist or has expired.

```dart
T? get<T>(String key)
```

**Parameters:**

* `key`: String identifier of the cached item

**Returns:**

* The cached value, or null if not found/expired

**Example:**

```dart
final prefs = Normie.cache.get<Map<String, String>>('user-preferences');
if (prefs != null) {
  print('Theme is: ${prefs['theme']}');
}
```

#### `remove`

Removes a specific item from the cache.

```dart
void remove(String key)
```

**Example:**

```dart
Normie.cache.remove('user-preferences');
```

#### `clear`

Removes all items from the cache.

```dart
void clear()
```

#### `has`

Checks if a key exists in the cache and hasn't expired.

```dart
bool has(String key)
```

#### `size`

Gets the current number of items in the cache.

```dart
int get size
```

#### `keys`

Gets a list of all cache keys.

```dart
List<String> get keys
```

#### `removeExpired`

Manually removes all expired items from the cache.

```dart
void removeExpired()
```

### Common Use Cases

1. **API Response Caching**

```dart
Future<UserData> getUserProfile(String userId) async {
  // Check cache first
  final cached = Normie.cache.get<UserData>('user-$userId');
  if (cached != null) return cached;

  // If not in cache, fetch from API
  final response = await api.getUser(userId);
  
  // Cache for 5 minutes
  Normie.cache.set('user-$userId', response, 
    expiry: Duration(minutes: 5));
    
  return response;
}
```

2. **App Configuration**

```dart
void cacheAppConfig(Map<String, dynamic> config) {
  Normie.cache.set('app-config', config,
    expiry: Duration(hours: 24));
}
```

3. **Temporary Data Storage**

```dart
void cacheFormData(Map<String, dynamic> formData) {
  Normie.cache.set('draft-form', formData,
    expiry: Duration(minutes: 30));
}
```

### Tips & Tricks

1. **Memory Management**
   * Regularly call `removeExpired()` to clean up expired items
   * Use appropriate expiry times to prevent memory bloat
   * Clear specific sections of cache when logging out users
2. **Type Safety**

```dart
// Bad ❌
final data = Normie.cache.get('my-data'); // dynamic type

// Good ✅
final data = Normie.cache.get<Map<String, dynamic>>('my-data');
```

3. **Checking Before Operations**

```dart
// Defensive programming
if (Normie.cache.has('user-data')) {
  final data = Normie.cache.get<UserData>('user-data');
  // Process data...
}
```

### Performance Considerations

* Cache accesses are O(1) operations
* Regular cleanup helps maintain optimal performance
* Consider using `size` to monitor cache growth
* For large objects, consider implementing size limits
