Cache Network Media
The ultimate Flutter plugin for caching network images, SVGs, and Lottie animations with persistent disk storage and offline support.
Why Cache Network Media?
Tired of your app downloading the same images repeatedly? Want seamless offline support for your media assets? Cache Network Media provides a unified, efficient solution for caching all your network media in Flutter.
✨ Key Benefits
| Benefit | Description |
|---|---|
| 🚀 Faster Load Times | Media loads instantly from local cache after first download |
| 📴 Offline Support | Display cached media even without internet connection |
| 💾 Reduced Bandwidth | Download once, use forever - saves data for your users |
| 🎯 Unified API | One widget for images, SVGs, and Lottie - consistent syntax |
| 📁 Custom Cache Directory | Full control over where your cached files are stored |
| 🔧 Zero Configuration | Works out of the box with sensible defaults |
| 📱 Cross-Platform | Android, iOS with native platform channel support |
Feature Comparison
Supported Media Types
| Media Type | Supported | Caching Method | Use Case |
|---|---|---|---|
| PNG | ✅ | Binary | Photos, screenshots, graphics |
| JPG/JPEG | ✅ | Binary | Photos, compressed images |
| WebP | ✅ | Binary | Modern web images, animations |
| GIF | ✅ | Binary | Animated images |
| BMP | ✅ | Binary | Bitmap images |
| SVG | ✅ | Binary | Vector icons, logos, illustrations |
| Lottie JSON | ✅ | Binary | Animations, micro-interactions |
Feature Matrix
| Feature | cache_network_media | Others |
|---|---|---|
| Image Caching | ✅ | ✅ |
| SVG Support | ✅ | ❌ |
| Lottie Support | ✅ | ❌ |
| Custom Cache Directory | ✅ | ❌ |
| Offline Support | ✅ | ⚠️ |
| Tap Gesture Support | ✅ | ❌ |
| Unified API | ✅ | ❌ |
| Platform Channel Support | ✅ | ⚠️ |
| Privacy Manifest (iOS) | ✅ | ❌ |
| Swift Package Manager | ✅ | ⚠️ |
Installation
Add to your pubspec.yaml:
dependencies:
cache_network_media: ^1.1.0
Then run:
flutter pub get
Quick Start
Cache Network Images
CacheNetworkMediaWidget.img(
url: 'https://example.com/image.png',
width: 200,
height: 200,
fit: BoxFit.cover,
placeholder: CircularProgressIndicator(),
onTap: () => debugPrint('Image tapped!'),
)
Cache SVG Graphics
CacheNetworkMediaWidget.svg(
url: 'https://example.com/icon.svg',
width: 100,
height: 100,
color: Colors.blue,
onTap: () => debugPrint('SVG tapped!'),
)
Cache Lottie Animations
CacheNetworkMediaWidget.lottie(
url: 'https://example.com/animation.json',
width: 300,
height: 300,
repeat: true,
animate: true,
onTap: () => debugPrint('Animation tapped!'),
)
Use as an ImageProvider
CacheNetworkMediaImageProvider uses the same disk cache, and works anywhere Flutter accepts an ImageProvider:
// Avatars
CircleAvatar(
backgroundImage: CacheNetworkMediaImageProvider('https://example.com/avatar.png'),
)
// Backgrounds
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: CacheNetworkMediaImageProvider('https://example.com/bg.jpg'),
fit: BoxFit.cover,
),
),
)
// Warm the cache before navigating
await precacheImage(
CacheNetworkMediaImageProvider('https://example.com/hero.png'),
context,
);
// Decode thumbnails at a smaller size to save memory
Image(
image: ResizeImage(
CacheNetworkMediaImageProvider('https://example.com/photo.jpg'),
width: 200,
),
)
Save memory with thumbnails
Decode large images at the size you display them. Values are in physical pixels:
CacheNetworkMediaWidget.img(
url: 'https://example.com/photo.jpg',
width: 100,
height: 100,
memCacheWidth: (100 * MediaQuery.devicePixelRatioOf(context)).round(),
)
With CacheNetworkMediaImageProvider, wrap it in ResizeImage as shown above.
Cache control
Set these once, before runApp. They apply to images, SVGs and Lottie files:
void main() {
// Download again after 7 days. While offline, the expired copy is still shown.
CacheNetworkMedia.maxAge = const Duration(days: 7);
// Keep the disk cache under 200 MB, deleting least recently used files first.
CacheNetworkMedia.maxCacheSizeBytes = 200 * 1024 * 1024;
runApp(const MyApp());
}
Both default to null (never expire, no size limit).
Manage the cache directly:
// Download ahead of time, e.g. before the user goes offline
await CacheNetworkMedia.prefetch('https://example.com/onboarding.json');
// Remove one file, e.g. after the user changes their avatar
await CacheNetworkMedia.evict('https://example.com/avatar.png');
// Remove everything, e.g. on logout
await CacheNetworkMedia.clear();
If you use a custom cacheDirectory, pass the same directory to these methods.
Advanced Usage
Custom Cache Directory
Take full control over where your cached files are stored. This is useful for:
- Organizing cached files by feature or user
- Managing cache size by clearing specific directories
- Sharing cache between different parts of your app
- Debugging by easily locating cached files
import 'dart:io';
// Use a custom directory for caching
final customDir = Directory('/path/to/your/cache');
CacheNetworkMediaWidget.img(
url: 'https://example.com/image.png',
cacheDirectory: customDir,
)
Error Handling
Handle network failures gracefully:
CacheNetworkMediaWidget.img(
url: 'https://example.com/image.png',
placeholder: CircularProgressIndicator(),
errorBuilder: (context, error, stackTrace) {
return Column(
children: [
Icon(Icons.error, color: Colors.red),
Text('Failed to load image'),
],
);
},
)
Image with Color Blending
CacheNetworkMediaWidget.img(
url: 'https://example.com/image.png',
color: Colors.blue,
colorBlendMode: BlendMode.multiply,
filterQuality: FilterQuality.high,
)
SVG with Theme Support
CacheNetworkMediaWidget.svg(
url: 'https://example.com/icon.svg',
colorFilter: ColorFilter.mode(Colors.red, BlendMode.srcIn),
theme: SvgTheme(currentColor: Colors.blue),
semanticsLabel: 'App logo',
)
Lottie with Animation Control
CacheNetworkMediaWidget.lottie(
url: 'https://example.com/animation.json',
repeat: false, // Play once
reverse: true, // Play in reverse
animate: true, // Auto-start
frameRate: 60.0, // Custom FPS
addRepaintBoundary: true, // Performance optimization
)
Lazy Loading for Performance Optimization
Enable true lazy loading to defer media loading until the widget is actually visible in the viewport. Uses the visibility_detector package internally:
// Image with lazy loading
CacheNetworkMediaWidget.img(
url: 'https://example.com/image.png',
width: 400,
height: 300,
lazyLoading: true, // Loads only when visible
)
// SVG with lazy loading
CacheNetworkMediaWidget.svg(
url: 'https://example.com/icon.svg',
width: 100,
height: 100,
lazyLoading: true,
)
// Lottie with lazy loading
CacheNetworkMediaWidget.lottie(
url: 'https://example.com/animation.json',
width: 200,
height: 200,
lazyLoading: true,
repeat: true,
)
How it works:
ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return CacheNetworkMediaWidget.img(
url: 'https://example.com/image$index.png',
width: double.infinity,
height: 200,
lazyLoading: true, // Only loads when scrolled into view!
placeholder: const Center(
child: CircularProgressIndicator(),
),
);
},
)
What Lazy Loading Does:
- ✅ Waits for widgets to scroll into the viewport before loading
- ✅ Works with vertical scrolling (ListView)
- ✅ Works with horizontal scrolling (ListView with scrollDirection: Axis.horizontal)
- ✅ Works with GridView and other scrollable widgets
- ✅ Only starts network request when widget becomes visible
- ✅ Saves bandwidth by not loading off-screen media
- ✅ Reduces memory usage significantly
Benefits:
- ⚡ Faster initial page load (only loads visible items)
- 💾 Dramatically reduced memory usage (no off-screen loading)
- 📶 Lower bandwidth consumption (loads on-demand)
- 🔋 Better battery life
- 📱 Smooth scrolling performance
- 🎯 Perfect for long lists and grids
Technical Details:
- Uses
visibility_detectorpackage for viewport detection - Triggers loading when
visibleFraction > 0(even partially visible) - Automatically handles both horizontal and vertical scrolling
- Minimal performance overhead
API Reference
Common Parameters (All Media Types)
| Parameter | Type | Description |
|---|---|---|
url |
String |
Required. The network URL of the media |
cacheDirectory |
Directory? |
Custom directory for caching. Uses platform default if null |
width |
double? |
Width of the widget |
height |
double? |
Height of the widget |
fit |
BoxFit? |
How to inscribe the media into the allocated space |
alignment |
AlignmentGeometry |
How to align the media within its bounds |
placeholder |
Widget? |
Widget shown while loading |
errorBuilder |
Function? |
Builder for error widget |
onTap |
VoidCallback? |
Callback when widget is tapped |
Image-Specific Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
color |
Color? |
null | Color to blend with image |
colorBlendMode |
BlendMode? |
null | Blend mode for color |
filterQuality |
FilterQuality |
medium | Quality of image sampling |
repeat |
ImageRepeat |
noRepeat | How to paint uncovered portions |
semanticLabel |
String? |
null | Accessibility label |
SVG-Specific Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
color |
Color? |
null | Simple color tinting |
colorFilter |
ColorFilter? |
null | Advanced color filtering |
theme |
SvgTheme? |
null | SVG theme for styling |
clipBehavior |
Clip |
hardEdge | How to clip content |
Lottie-Specific Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
repeat |
bool |
true | Loop the animation |
reverse |
bool |
false | Play in reverse |
animate |
bool |
true | Start immediately |
frameRate |
double? |
null | Custom FPS |
delegates |
LottieDelegates? |
null | Custom delegates |
How Caching Works
┌─────────────────────────────────────────────────────────────┐
│ Cache Flow Diagram │
├─────────────────────────────────────────────────────────────┤
│ │
│ Request URL ──► Check Cache ──► Cache Hit? ──► Yes ──► │
│ │ │ Return │
│ │ │ Cached │
│ │ ▼ │
│ │ No │
│ │ │ │
│ │ ▼ │
│ │ Download from │
│ │ Network │
│ │ │ │
│ │ ▼ │
│ │ Save to Cache │
│ │ │ │
│ │ ▼ │
│ └─────────────────────► Return Media │
│ │
└─────────────────────────────────────────────────────────────┘
Cache Storage
All media types are stored as .cache files in a cache_network_media/ folder inside the platform cache directory:
| Platform | Cache directory |
|---|---|
| iOS | Library/Caches (persists between launches, not backed up) |
| Android | App-specific external cache, or internal cache if external storage is unavailable |
Pass cacheDirectory to use a different location.
Platform Support
| Platform | Status | Notes |
|---|---|---|
| Android | ✅ | Full support with method channels |
| iOS | ✅ | Swift Package Manager + Privacy Manifest |
| Web | 🚧 | Coming soon |
| macOS | 🚧 | Coming soon |
| Windows | 🚧 | Coming soon |
| Linux | 🚧 | Coming soon |
Performance Tips
- Use appropriate image sizes - Don't load 4K images for thumbnails
- Leverage custom cache directories - Organize cache by feature for easier management
- Set dimensions when known - Provide
widthandheightto avoid layout shifts - Use
addRepaintBoundary- Enabled by default for Lottie, improves performance - Handle errors gracefully - Always provide an
errorBuilderfor production apps
Migration Guide
From cached_network_image
// Before (cached_network_image)
CachedNetworkImage(
imageUrl: 'https://example.com/image.png',
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
// After (cache_network_media)
CacheNetworkMediaWidget.img(
url: 'https://example.com/image.png',
placeholder: CircularProgressIndicator(),
errorBuilder: (context, error, stackTrace) => Icon(Icons.error),
)
// Before (cached_network_image)
CircleAvatar(backgroundImage: CachedNetworkImageProvider(url))
// After (cache_network_media)
CircleAvatar(backgroundImage: CacheNetworkMediaImageProvider(url))
Documentation
Contributing
We welcome contributions! Please read our Contributing Guidelines before submitting a PR.
# Clone the repository
git clone https://github.com/D-extremity/cache_network_media.git
# Install dependencies
flutter pub get
# Run tests
flutter test
# Check formatting
dart format --set-exit-if-changed .
# Run analyzer
flutter analyze
License
MIT License - see LICENSE for details.
Author
Created with ❤️ by @D-extremity
Support
If this package helped you, please:
- ⭐ Star the GitHub repository
- 👍 Like on pub.dev
- 🐛 Report issues on GitHub Issues
Cache Network Media - Making network media caching simple since 2025
Libraries
- cache_network_media
- Cache Network Media - A Flutter plugin for caching network media