flutter_app_cache_manager 1.0.1 copy "flutter_app_cache_manager: ^1.0.1" to clipboard
flutter_app_cache_manager: ^1.0.1 copied to clipboard

A comprehensive Flutter cache manager package to cache images, videos, and other files.

Flutter App Cache Manager #

A comprehensive and flexible cache manager for Flutter applications built on top of flutter_cache_manager. This package provides a clean architecture approach to caching with support for multiple file types, cache policies, monitoring, and maintenance operations.

πŸš€ Latest Updates (v1.0.1) #

  • Enhanced Type Safety: Improved safe type parsing with better error handling
  • Better Architecture: Refined interface naming and code organization
  • Improved Performance: Optimized cache operations and memory usage
  • Enhanced Documentation: Better API documentation and examples

🌟 Features #

Core Functionality #

  • Multi-file type support: Images, videos, audio, documents, archives, and general files
  • Clean Architecture: Interface-based design with dependency inversion
  • Type Safety: Uses flutter_shared_utilities for safe type parsing with enhanced error handling
  • Cache Policies: TTL, LRU, FIFO, and custom expiration policies
  • Priority System: Critical, high, normal, and low priority levels

Advanced Capabilities #

  • Progress Monitoring: Real-time download progress tracking
  • Event Streaming: Comprehensive cache event notifications
  • Batch Operations: Store, retrieve, and delete multiple entries
  • Cache Statistics: Hit rates, usage analytics, and performance metrics
  • Integrity Validation: Checksum-based corruption detection and repair
  • Smart Cleanup: Automatic maintenance with configurable policies

Configuration Options #

  • File Type Specific: Optimized settings for different content types
  • Network Management: WiFi-only mode, retry policies, timeouts
  • Storage Control: Size limits, entry limits, compression, encryption
  • Flexible TTL: Per-entry or global time-to-live settings

πŸ“¦ Installation #

Add this package to your pubspec.yaml:

dependencies:
  flutter_app_cache_manager: ^1.0.1
  flutter_shared_utilities: ^1.0.7

Then run:

flutter pub get

πŸš€ Quick Start #

Basic Usage #

import 'package:flutter_app_cache_manager/flutter_app_cache_manager.dart';

// Create configuration for images
final config = CacheConfigurationModel.imageConfig().copyWith(
  name: 'my_app_cache',
  maxCacheSize: 100 * 1024 * 1024, // 100MB
);

// Create and initialize the cache manager
final cacheManager = await FlutterCacheManagerImpl.create(config);

// Store an image
final imageEntry = await cacheManager.storeImage(
  key: 'profile_image_123',
  url: 'https://example.com/profile.jpg',
  ttl: const Duration(days: 7),
);

// Retrieve from cache
final cachedEntry = await cacheManager.retrieve('profile_image_123');
if (cachedEntry != null) {
  final file = await cacheManager.getFile('profile_image_123');
  // Use the cached file
}

// Cleanup when done
await cacheManager.dispose();

Configuration Types #

The package provides pre-configured setups for different file types:

// Image-optimized configuration
final imageConfig = CacheConfigurationModel.imageConfig();

// Video-optimized configuration (WiFi-only by default)
final videoConfig = CacheConfigurationModel.videoConfig();

// Audio-optimized configuration
final audioConfig = CacheConfigurationModel.audioConfig();

// Document-optimized configuration
final documentConfig = CacheConfigurationModel.documentConfig();

// Custom configuration
final customConfig = CacheConfigurationModel(
  name: 'custom_cache',
  maxCacheSize: 200 * 1024 * 1024, // 200MB
  maxCacheEntries: 1000,
  defaultTtl: const Duration(hours: 24),
  expirationPolicy: CacheExpirationPolicy.lru,
  autoCleanupEnabled: true,
  wifiOnlyMode: false,
);

πŸ“– Detailed Usage #

Storing Different File Types #

// Store an image with specific options
final imageEntry = await cacheManager.storeImage(
  key: 'user_avatar_456',
  url: 'https://api.example.com/avatars/456.jpg',
  ttl: const Duration(days: 30),
  headers: {'Authorization': 'Bearer token'},
);

// Store a video
final videoEntry = await cacheManager.storeVideo(
  key: 'tutorial_video',
  url: 'https://videos.example.com/tutorial.mp4',
  ttl: const Duration(days: 7),
);

// Store an audio file
final audioEntry = await cacheManager.storeAudio(
  key: 'notification_sound',
  url: 'https://sounds.example.com/notification.wav',
  ttl: const Duration(days: 365), // Cache for a year
);

// Store a document
final docEntry = await cacheManager.storeDocument(
  key: 'user_manual',
  url: 'https://docs.example.com/manual.pdf',
  ttl: const Duration(days: 90),
);

// Store raw data directly
final Uint8List imageData = ...; // Your image data
final dataEntry = await cacheManager.store(
  key: 'generated_image',
  url: 'internal://generated',
  data: imageData,
  fileType: CacheFileType.image,
  priority: CachePriority.high,
);

Batch Operations #

// Store multiple files at once
final List<Map<String, Object?>> filesToCache = [
  {
    'key': 'image1',
    'url': 'https://example.com/image1.jpg',
    'fileType': CacheFileType.image,
  },
  {
    'key': 'image2',
    'url': 'https://example.com/image2.jpg',
    'fileType': CacheFileType.image,
  },
];

final List<CacheEntryModel> storedEntries = await cacheManager.storeMultiple(filesToCache);

// Retrieve multiple entries
final List<String> keys = ['image1', 'image2', 'image3'];
final List<CacheEntryModel?> entries = await cacheManager.retrieveMultiple(keys);

// Delete multiple entries
final List<bool> deleteResults = await cacheManager.deleteMultiple(keys);

// Preload URLs for faster access later
final List<String> urlsToPreload = [
  'https://example.com/future-image1.jpg',
  'https://example.com/future-image2.jpg',
];
await cacheManager.preloadUrls(urlsToPreload, fileType: CacheFileType.image);

Cache Management and Analytics #

// Get cache statistics
final Map<String, Object?> stats = await cacheManager.getCacheStatistics();
print('Cache hit rate: ${stats['hitRate']}%');
print('Total size: ${stats['totalSize']} bytes');
print('Total entries: ${stats['totalEntries']}');

// Get entries by different criteria
final List<CacheEntryModel> imageEntries = await cacheManager.getEntriesByType(CacheFileType.image);
final List<CacheEntryModel> highPriorityEntries = await cacheManager.getEntriesByPriority(CachePriority.high);
final List<CacheEntryModel> expiredEntries = await cacheManager.getExpiredEntries();

// Get usage statistics by file type
final Map<CacheFileType, int> usage = await cacheManager.getCacheUsageByType();
for (final entry in usage.entries) {
  print('${entry.key.value}: ${entry.value} bytes');
}

// Get largest cached files
final List<CacheEntryModel> largestFiles = await cacheManager.getLargestEntries(limit: 10);

// Get most accessed files
final List<CacheEntryModel> mostAccessed = await cacheManager.getMostAccessedEntries(limit: 10);

Progress Monitoring and Events #

// Listen to cache events
final StreamSubscription eventSub = cacheManager.cacheEventStream.listen((CacheEvent event) {
  switch (event.type) {
    case CacheEventType.downloadStarted:
      print('Download started: ${event.key}');
      break;
    case CacheEventType.downloadCompleted:
      print('Download completed: ${event.key}');
      break;
    case CacheEventType.downloadFailed:
      print('Download failed: ${event.key}');
      break;
    case CacheEventType.entryAccessed:
      print('Entry accessed: ${event.key}');
      break;
    case CacheEventType.cleanupPerformed:
      print('Cleanup performed: ${event.data}');
      break;
  }
});

// Listen to download progress
final StreamSubscription progressSub = cacheManager.downloadProgressStream.listen((Map<String, double> progress) {
  progress.forEach((String key, double progress) {
    print('$key: ${(progress * 100).toStringAsFixed(1)}% complete');
  });
});

// Don't forget to cancel subscriptions
await eventSub.cancel();
await progressSub.cancel();

Cache Maintenance #

// Clean up expired entries
final int expiredCount = await cacheManager.cleanupExpired();
print('Cleaned up $expiredCount expired entries');

// Clean up by size (when cache is too large)
final int sizeCleanupCount = await cacheManager.cleanupBySize();
print('Cleaned up $sizeCleanupCount entries to reduce size');

// LRU cleanup (keep only most recently used)
final int lruCount = await cacheManager.cleanupLRU(targetCount: 100);
print('LRU cleanup removed $lruCount entries');

// Validate cache integrity
final List<String> corruptedKeys = await cacheManager.validateIntegrity();
if (corruptedKeys.isNotEmpty) {
  print('Found ${corruptedKeys.length} corrupted files');

  // Repair corrupted entries
  final int repairedCount = await cacheManager.repairCorrupted();
  print('Repaired $repairedCount corrupted entries');
}

// Comprehensive maintenance
final Map<String, int> maintenanceResults = await cacheManager.performMaintenance();
print('Maintenance results: $maintenanceResults');

// Full optimization
await cacheManager.optimize();

πŸ—οΈ Architecture #

This package follows Clean Architecture principles:

lib/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ core/
β”‚   β”‚   β”œβ”€β”€ constants/     # Cache configuration constants
β”‚   β”‚   β”œβ”€β”€ enums/         # Cache-related enumerations
β”‚   β”‚   └── exceptions/    # Custom exception classes
β”‚   β”œβ”€β”€ interfaces/        # Abstract cache manager interface
β”‚   β”œβ”€β”€ models/           # Data models (Entry, Configuration)
β”‚   └── implementations/  # Concrete cache manager implementation

Key Components #

  • BaseCacheManagerInterface: Base abstract interface defining common cache operations
  • FlutterCacheManagerImpl: Concrete implementation using flutter_cache_manager
  • CacheEntryModel: Represents a cached file with metadata
  • CacheConfigurationModel: Cache settings and policies
  • Enums: Type-safe enumerations for cache policies, file types, priorities
  • Exceptions: Specific exceptions for different error scenarios

πŸ› οΈ Customization #

Creating Custom Cache Managers #

class CustomCacheManager extends FlutterCacheManagerImpl {
  // Add domain-specific methods

  Future<CacheEntryModel> storeUserProfileImage({
    required String userId,
    required String imageUrl,
    Uint8List? imageData,
  }) async {
    final key = 'user_profile_$userId';
    return await storeImage(
      key: key,
      url: imageUrl,
      imageData: imageData,
      ttl: const Duration(days: 7),
      priority: CachePriority.high, // Profile images are important
    );
  }

  Future<List<CacheEntryModel>> getAllUserProfileImages() async {
    final allEntries = await getAllEntries();
    return allEntries.where((entry) =>
      entry.key.startsWith('user_profile_') &&
      entry.fileType == CacheFileType.image
    ).toList();
  }
}

Custom Configuration #

// Create highly customized configuration
final advancedConfig = CacheConfigurationModel(
  name: 'advanced_cache',
  maxCacheSize: 500 * 1024 * 1024, // 500MB
  maxCacheEntries: 5000,
  defaultTtl: const Duration(hours: 12),
  expirationPolicy: CacheExpirationPolicy.lru,
  storageLevel: CacheStorageLevel.multiLevel,
  autoCleanupEnabled: true,
  cleanupThreshold: 0.85, // Start cleanup at 85% full
  cleanupTargetRatio: 0.70, // Clean down to 70%
  wifiOnlyMode: false,
  maxConcurrentDownloads: 4,
  networkTimeout: const Duration(seconds: 30),
  downloadTimeout: const Duration(minutes: 5),
  retryAttempts: 3,
  retryDelay: const Duration(seconds: 2),
  validateIntegrity: true,
  enableCompression: true,
  customHeaders: {
    'User-Agent': 'MyApp/1.0',
    'Cache-Control': 'max-age=3600',
  },
  metadata: {
    'app_version': '1.0.0',
    'cache_version': '2',
  },
);

πŸ§ͺ Testing #

The package is designed for testability with its interface-based architecture:

// Create a mock implementation for testing
class MockCacheManager implements BaseCacheManagerInterface {
  final Map<String, CacheEntryModel> _mockCache = {};

  @override
  Future<CacheEntryModel> store({required String key, required String url, ...}) async {
    final entry = CacheEntryModel(key: key, url: url, ...);
    _mockCache[key] = entry;
    return entry;
  }

  @override
  Future<CacheEntryModel?> retrieve(String key) async {
    return _mockCache[key];
  }

  // Implement other methods...
}

// Use in tests
void main() {
  group('Cache Manager Tests', () {
    late BaseCacheManagerInterface cacheManager;

    setUp(() {
      cacheManager = MockCacheManager();
    });

    test('should store and retrieve entry', () async {
      // Test implementation
    });
  });
}

πŸ“± Integration with Flutter Widgets #

Cached Network Image Integration #

import 'package:cached_network_image/cached_network_image.dart';

class CachedImageWidget extends StatelessWidget {
  final String imageUrl;
  final FlutterCacheManagerImpl cacheManager;

  const CachedImageWidget({
    super.key,
    required this.imageUrl,
    required this.cacheManager,
  });

  @override
  Widget build(BuildContext context) {
    return CachedNetworkImage(
      imageUrl: imageUrl,
      cacheManager: cacheManager._cacheManagers[CacheFileType.image],
      placeholder: (context, url) => const CircularProgressIndicator(),
      errorWidget: (context, url, error) => const Icon(Icons.error),
      fadeInDuration: const Duration(milliseconds: 300),
    );
  }
}

Progress Indicator #

class DownloadProgressWidget extends StatefulWidget {
  final String cacheKey;
  final FlutterCacheManagerImpl cacheManager;

  const DownloadProgressWidget({
    super.key,
    required this.cacheKey,
    required this.cacheManager,
  });

  @override
  State<DownloadProgressWidget> createState() => _DownloadProgressWidgetState();
}

class _DownloadProgressWidgetState extends State<DownloadProgressWidget> {
  double _progress = 0.0;
  late StreamSubscription _subscription;

  @override
  void initState() {
    super.initState();
    _subscription = widget.cacheManager.downloadProgressStream.listen((progress) {
      if (progress.containsKey(widget.cacheKey)) {
        setState(() {
          _progress = progress[widget.cacheKey]!;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return LinearProgressIndicator(value: _progress);
  }

  @override
  void dispose() {
    _subscription.cancel();
    super.dispose();
  }
}

⚑ Performance Tips #

  1. Use appropriate TTL values: Don't cache files longer than necessary
  2. Set reasonable cache sizes: Monitor storage usage and adjust limits
  3. Enable cleanup: Let the cache manager handle maintenance automatically
  4. Use priorities: Mark critical files as high priority to prevent cleanup
  5. Batch operations: Use storeMultiple/retrieveMultiple for better performance
  6. Monitor hit rates: Low hit rates might indicate inefficient caching strategies

πŸ”’ Security Considerations #

  • Enable encryption for sensitive cached data
  • Validate checksums to ensure data integrity
  • Use HTTPS URLs for all network requests
  • Clear cache when users log out
  • Set appropriate TTL for sensitive content

πŸ› Troubleshooting #

Common Issues #

Cache not initializing

// Use the factory constructor to create and initialize
final cacheManager = await FlutterCacheManagerImpl.create(configuration);

Files not being cached

// Check if cache is enabled
print('Cache enabled: ${cacheManager.isEnabled}');

// Verify configuration
print('Max cache size: ${cacheManager.configuration.maxCacheSize}');

High memory usage

// Enable cleanup and set reasonable limits
final config = CacheConfigurationModel.imageConfig().copyWith(
  maxCacheSize: 50 * 1024 * 1024, // 50MB
  autoCleanupEnabled: true,
  cleanupThreshold: 0.8,
);

Debug Mode #

Enable debug mode for detailed logging:

final debugConfig = configuration.copyWith(debugMode: true);
final cacheManager = await FlutterCacheManagerImpl.create(debugConfig);

🀝 Contributing #

Contributions are welcome! Please read our contributing guidelines and submit pull requests for any improvements.

πŸ“„ License #

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments #


πŸ“š API Reference #

Core Classes #

BaseCacheManagerInterface

Abstract interface defining all cache operations.

FlutterCacheManagerImpl

Main implementation class providing comprehensive caching functionality.

CacheEntryModel

Represents a cached file with comprehensive metadata including:

  • File information (size, type, path)
  • Cache metadata (TTL, priority, tags)
  • Access statistics (hit count, last accessed)
  • Integrity data (checksum, corruption status)

CacheConfigurationModel

Configuration class with factory methods for different file types:

  • defaultConfig() - Basic configuration
  • imageConfig() - Optimized for images
  • videoConfig() - Optimized for videos (WiFi-only by default)
  • audioConfig() - Optimized for audio files
  • documentConfig() - Optimized for documents

Enums #

  • CacheFileType: image, video, audio, document, archive, general
  • CacheExpirationPolicy: never, ttl, lastAccessed, lru, fifo, custom
  • CachePriority: low, normal, high, critical
  • CacheStorageLevel: memory, disk, multiLevel

For complete API documentation, see the inline documentation in the source code.

0
likes
150
points
61
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter cache manager package to cache images, videos, and other files.

Repository (GitHub)
View/report issues

Topics

#cache #cache-manager #audio-cache #video-cache #image-cache

Documentation

API reference

License

MIT (license)

Dependencies

app_logger_manager, crypto, flutter, flutter_cache_manager, flutter_shared_utilities, http, mime, path, path_provider

More

Packages that depend on flutter_app_cache_manager