A developer-friendly, user-transparent cache manager for Flutter apps — inspired by Telegram's Storage Usage screen.

- Named Buckets — Isolated cache zones per feature (images, API, user data)
- Multiple Backends — Memory, SharedPrefs, SQLite, File System, Hybrid (L1+L2)
- Eviction Strategies — LRU, LFU, FIFO, Priority-based
- TTL & Expiry — Per-item or per-bucket time-to-live with lazy + proactive purge
- Cache Patterns —
cacheOrFetch, staleWhileRevalidate out of the box
- Tagging — Tag items at write time, bulk-invalidate by tag across all buckets
- Encryption — AES-256 encrypted buckets with transparent read/write
- Diagnostics — Hit/miss rates, size tracking, event streams, debug overlay
- Ready-Made UI — Telegram-style storage manager screen, donut chart, bucket tiles
- Zero Config UI — Widgets read from CacheVault directly, just drop in and go
dependencies:
flutter_cache_vault: ^1.0.0
flutter pub get
import 'package:flutter_cache_vault/flutter_cache_vault.dart';
import 'package:flutter_cache_vault/ui.dart';
// 1. Initialize
await CacheVault.init(CacheConfig(
globalMaxSize: 500 * 1024 * 1024,
defaultTTL: Duration(days: 7),
defaultBackend: BackendType.memory,
));
// 2. Create a bucket
final images = CacheVault.bucket('images', BucketOptions(
maxSize: 100 * 1024 * 1024,
ttl: Duration(days: 30),
evictionStrategy: EvictionStrategy.lru,
displayName: 'Images',
));
// 3. Read & Write
await images.set('avatar_123', imageBytes);
final data = await images.get<Uint8List>('avatar_123');
// 4. Show the storage manager UI
Navigator.push(context, MaterialPageRoute(
builder: (_) => CacheManagerScreen(),
));
| Class |
Description |
CacheVault |
Main singleton — init(), bucket(), clearAll(), report() |
CacheBucket |
Named cache zone — set(), get(), delete(), clear(), cacheOrFetch() |
CacheConfig |
Global configuration — max size, default TTL, backend, encryption |
BucketOptions |
Per-bucket config — max size, TTL, eviction, backend, group, display |
CacheEvent |
Event model for the stream system |
CacheReport |
Diagnostics report with per-bucket breakdowns |
ByteFormatter |
Utility for human-readable byte formatting |
| Method |
Description |
bucket.set(key, value, {ttl, tags, priority}) |
Store a value |
bucket.get<T>(key) |
Retrieve a value (returns null if missing/expired) |
bucket.has(key) |
Check existence |
bucket.delete(key) |
Delete one item |
bucket.clear() |
Clear entire bucket |
bucket.setMany(map) |
Batch write |
bucket.getMany<T>(keys) |
Batch read |
| Method |
Description |
bucket.cacheOrFetch(key, fetcher: () => ...) |
Return cached or fetch fresh |
bucket.staleOrFetch(key, fetcher: () => ...) |
Return stale immediately, refresh in background |
| Method |
Description |
CacheVault.invalidateTag('user:123') |
Invalidate all items with a tag globally |
CacheVault.clearGroup('media') |
Clear all buckets in a group |
CacheVault.clearAll() |
Nuclear option |
CacheVault.purgeExpired() |
Remove all expired items |
| Strategy |
Enum |
Description |
| LRU |
EvictionStrategy.lru |
Evict least recently accessed |
| LFU |
EvictionStrategy.lfu |
Evict least frequently accessed |
| FIFO |
EvictionStrategy.fifo |
Evict oldest written |
| Priority |
EvictionStrategy.priority |
Evict lowest priority first |
| Backend |
Enum |
Best For |
| Memory |
BackendType.memory |
Session data, tokens |
| SharedPreferences |
BackendType.sharedPrefs |
Small KV, settings |
| SQLite |
BackendType.sqlite |
Large item counts, JSON |
| File System |
BackendType.file |
Images, videos, binary |
| Hybrid (L1+L2) |
BackendType.hybrid |
High-read + large payloads |
| Custom |
BackendType.custom |
Hive, Isar, ObjectBox |
| Widget |
Description |
CacheManagerScreen |
Full-page Telegram-style storage manager |
CacheBucketDetailScreen |
Drill-down view for a single bucket |
CacheUsageDonut |
Animated donut chart widget |
CacheBucketTile |
ListTile for one bucket (embed in settings) |
CacheDebugOverlay |
Dev-only floating debug badge |
CacheManagerTheme |
Full visual customization |
Full-screen storage manager with donut chart, bucket list, clear button, auto-remove policies, and max size slider.
Navigator.push(context, MaterialPageRoute(
builder: (_) => CacheManagerScreen(
title: 'Storage',
footerNote: 'Files are stored in the cloud and can be re-downloaded.',
theme: CacheManagerTheme(primaryColor: Colors.blue),
onClearComplete: (freedBytes) => print('Freed $freedBytes bytes'),
),
));
Wrap your app during development:
CacheDebugOverlay(
enabled: kDebugMode,
child: MyApp(),
)
await CacheVault.init(CacheConfig(
encryptionKey: 'my-32-character-encryption-key!!',
));
final secrets = CacheVault.bucket('secrets', BucketOptions(
encrypted: true,
));
await secrets.set('token', sensitiveData);
// Tag at write time
await apiCache.set('post_45', data, tags: ['user:123', 'posts']);
// Invalidate across ALL buckets
await CacheVault.invalidateTag('user:123');
final report = await CacheVault.report();
print('Total: ${ByteFormatter.format(report.totalSizeBytes)}');
for (final b in report.perBucket) {
print('${b.displayName}: ${b.hitRate * 100}% hit rate');
}
// Or pretty-print to console
await CacheVault.debugPrint();
CacheVault.events.listen((event) {
print('${event.type} in ${event.bucketName}: ${event.key}');
});
imageCache.onEvict.listen((event) => print('Evicted: ${event.key}'));
lib/
├── flutter_cache_vault.dart ← Pure Dart core (main export)
├── ui.dart ← Flutter UI widgets (optional import)
└── src/
├── core/ ← CacheVault, CacheBucket, models
├── eviction/ ← LRU, LFU, FIFO, Priority strategies
├── backends/ ← Memory, SharedPrefs, SQLite, File, Hybrid
├── serialization/ ← JSON, Bytes, custom serializer interface
├── encryption/ ← AES encrypted backend wrapper
├── migration/ ← Version-based data migration
└── ui/ ← All Flutter widgets
flutter test
MIT License — see LICENSE for details.
# CacheVault
# CacheVault