all_image_cache 0.0.2
all_image_cache: ^0.0.2 copied to clipboard
Flutter image cache with memory/disk layers, network/file/bytes sources, SVG support, optional compression, stale fallback, and production-ready widgets.
all_image_cache #
Português | English
Production-ready image caching for Flutter: memory + disk cache, network/file/bytes sources, SVG support, optional compression, stale fallback, negative caching, and widgets that are easy to test.
[all_image_cache hero]
Table of contents #
- Features
- Installing
- Quick start
- Step-by-step usage
- Supported image types
- Widgets
- Direct manager API
- Configuration
- Compression before saving
- SVG support
- Memory and decode size
- Negative cache and stale fallback
- Testing
- Comparison
- When to use it
- Documentation
- Contributors
- How to contribute
Features #
- L1 + L2 cache - fast in-memory reads backed by persistent storage.
- Network, file, and in-memory sources -
NetworkImageSource,FileImageSource, andBytesImageSource. - Raster and SVG widgets - use
CachedImagefor raster images andCachedSvgImagefor SVG. - Header-aware cache keys - authenticated image requests do not accidentally share cached bytes.
- Optional compression - plug
all_image_compressor your ownImageCompressor. - Stale fallback - expired bytes can still be returned when refresh fails.
- Negative caching - opt-in cache for known HTTP errors such as 404.
- Web-aware defaults - web uses an in-memory L2 store by default.
- Testable by design - the engine depends on contracts, so tests can inject fakes without real network or disk.
Installing #
flutter pub add all_image_cache
dependencies:
all_image_cache: ^0.0.1
import 'package:all_image_cache/all_image_cache.dart';
Quick start #
After installing the package and importing all_image_cache, most apps only
need two things:
- Initialize the cache once in
main. - Render the image with
CachedImageorCachedSvgImage.
Initialize the cache before runApp.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await AllImageCache.init();
runApp(const MyApp());
}
Render a cached network image.
class UserAvatar extends StatelessWidget {
const UserAvatar({super.key});
@override
Widget build(BuildContext context) {
return CachedImage.network(
'https://example.com/avatar.jpg',
width: 96,
height: 96,
fit: BoxFit.cover,
placeholderBuilder: (_) => const CircularProgressIndicator(),
errorBuilder: (_, error) => const Icon(Icons.broken_image),
);
}
}
That is enough for the default setup. The widget will fetch the image, store it in memory + disk cache, reuse it on the next render, and show your placeholder/error widgets when needed.
Step-by-step usage #
1. Add the package #
flutter pub add all_image_cache
2. Import it #
import 'package:all_image_cache/all_image_cache.dart';
3. Initialize once #
Call AllImageCache.init() before any cached image is rendered. A good place is main(), after WidgetsFlutterBinding.ensureInitialized().
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await AllImageCache.init();
runApp(const MyApp());
}
4. Use a cached raster image #
Use CachedImage for normal images such as JPG, PNG, WebP, GIF, and BMP.
CachedImage.network(
'https://example.com/products/42.jpg',
width: 120,
height: 120,
fit: BoxFit.cover,
placeholderBuilder: (_) => const Center(
child: CircularProgressIndicator(),
),
errorBuilder: (_, error) => const Icon(Icons.broken_image),
)
5. Use a cached SVG #
SVG is supported, but it uses a separate widget because Flutter's normal image decoder does not decode SVG.
CachedSvgImage.network(
'https://example.com/icons/cart.svg',
width: 32,
height: 32,
)
6. Use a local file #
CachedImage.file(
imageFile.path,
width: 160,
height: 160,
fit: BoxFit.cover,
)
For local SVG files:
CachedSvgImage.file(
svgFile.path,
width: 48,
height: 48,
)
7. Use bytes already in memory #
When you already have image bytes, provide a stable uniqueKey. The key is how the cache identifies those bytes later.
CachedImage.memory(
bytes,
uniqueKey: 'user-avatar-42',
width: 96,
height: 96,
fit: BoxFit.cover,
)
For SVG bytes:
CachedSvgImage.memory(
svgBytes,
uniqueKey: 'brand-logo-svg',
width: 120,
height: 40,
)
8. Use authenticated image URLs #
Headers are part of the cache key. This prevents two users or two tokens from accidentally sharing cached bytes.
CachedImage.network(
'https://api.example.com/me/avatar',
headers: {
'Authorization': 'Bearer $token',
},
)
9. Use it where Flutter requires ImageProvider #
Use CachedImageProvider for raster images in APIs like DecorationImage.
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: CachedImageProvider(
NetworkImageSource('https://example.com/background.jpg'),
),
fit: BoxFit.cover,
),
),
)
Supported image types #
all_image_cache caches bytes from network, file, or memory sources. Rendering support depends on which widget you use.
| Image type | Use | Notes |
|---|---|---|
| JPEG / JPG | CachedImage |
Supported by Flutter's raster decoder. |
| PNG | CachedImage |
Supported by Flutter's raster decoder. |
| WebP | CachedImage |
Supported by Flutter on the usual mobile, desktop, and web targets. |
| GIF | CachedImage |
Supported by Flutter's image pipeline. |
| BMP | CachedImage |
Supported where Flutter's decoder supports it. |
| Other Flutter raster formats | CachedImage |
If Image.memory can decode it on the target platform, CachedImage can render it. |
| SVG | CachedSvgImage |
Rendered through flutter_svg; do not use CachedImage for SVG. |
Important distinction:
CachedImageis for raster images decoded by Flutter.CachedSvgImageis for SVG.- The cache layer stores bytes; the widget decides how those bytes are rendered.
- Compression is intended for raster images. SVG entries are kept away from the raster compression path.
Widgets #
CachedImage #
Use it for raster formats decoded by Flutter, such as PNG, JPEG, WebP, GIF, BMP, and platform-supported image formats.
CachedImage.memory(
bytes,
uniqueKey: 'app://avatar/42',
cacheWidth: 192,
cacheHeight: 192,
)
CachedSvgImage #
Use it for SVG. SVG bytes are cached by the same engine but rendered through flutter_svg.
CachedSvgImage.network(
'https://example.com/icon.svg',
width: 32,
height: 32,
)
CachedImageProvider #
Use it when Flutter asks for an ImageProvider, for example DecorationImage.
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: CachedImageProvider(
NetworkImageSource('https://example.com/background.jpg'),
),
fit: BoxFit.cover,
),
),
)
CachedImageProvider is for raster images. Use CachedSvgImage for SVG.
Direct manager API #
You can read bytes directly when building your own UI or warming the cache.
final bytes = await AllImageCache.instance.getBytes(
const NetworkImageSource('https://example.com/photo.webp'),
);
await AllImageCache.instance.precache(
const NetworkImageSource('https://example.com/icon.svg'),
);
final stats = await AllImageCache.instance.stats();
Configuration #
await AllImageCache.init(
maxEntries: 300,
maxSizeBytes: 200 * 1024 * 1024,
memoryCacheMaxEntries: 120,
enableCompression: true,
negativeCacheDuration: const Duration(minutes: 5),
negativeCacheStatusCodes: const {404},
logger: const NoopCacheLogger(),
);
Everything important is injectable:
final manager = ImageCacheManager(
l1: myMemoryStore,
l2: myPersistentStore,
fetchers: [myFetcher],
keyGenerator: ValidationKeyGenerator(),
compressor: const NoopImageCompressor(),
);
Compression before saving #
Yes, all_image_cache can reduce raster images before saving them in the
persistent cache.
Enable compression during initialization:
await AllImageCache.init(
enableCompression: true,
);
Tune quality and maximum dimensions:
await AllImageCache.init(
enableCompression: true,
compressOptions: const ImageCompressOptions(
quality: 72,
maxWidth: 1080,
maxHeight: 1080,
),
);
What happens:
- The original bytes are fetched from network, file, or memory.
- Raster bytes are compressed.
- The compressed bytes are saved in L2 disk cache.
- Future reads use the smaller cached bytes.
Use this when remote images are much larger than your UI needs, such as product grids, avatars, feeds, galleries, or chat images.
Example result:
Before saving in cache
Original raster bytes ████████████████████ 100%
Compressed raster bytes ████████ ~40%
SVG bytes ████████████████████ 100% (not compressed)
Compression support by format:
| Format | Compressed before saving? | Why |
|---|---|---|
| JPEG / JPG | Yes | Raster format; useful for reducing quality and dimensions. |
| PNG | Yes | Raster format; useful when dimensions are larger than the UI needs. |
| WebP | Yes | Raster format; can be reduced before persistent cache writes. |
| GIF / animated images | Depends on compressor support | Keep tests for your target format if animation matters. |
| BMP and other raster formats | Depends on compressor support | Cache works; compression depends on the configured compressor. |
| SVG | No | SVG is XML/vector data and is rendered by flutter_svg, not the raster decoder. |
You can also provide your own compressor:
await AllImageCache.init(
compressor: MyImageCompressor(),
compressOptions: const ImageCompressOptions(
quality: 80,
maxWidth: 1600,
),
);
compressor overrides enableCompression. SVG files are not sent through the
raster compression path.
SVG support #
CachedImage intentionally stays raster-only. SVG is a different rendering path, so all_image_cache exposes CachedSvgImage.
This prevents the classic Could not instantiate image codec error that happens when SVG bytes are sent to Flutter's raster image decoder.
SVG bytes are also skipped by the compression step, so enabling compression for JPEG/PNG does not corrupt SVG entries.
Memory and decode size #
Large images in long lists can exhaust memory if decoded at full resolution. Use cacheWidth and cacheHeight on CachedImage to request a smaller decoded image.
CachedImage.network(
url,
width: 80,
height: 80,
cacheWidth: 160,
cacheHeight: 160,
)
This wraps the image provider with ResizeImage.resizeIfNeeded.
Negative cache and stale fallback #
By default, HTTP errors are not cached. If you want to avoid repeatedly requesting known-missing images, enable negative cache:
await AllImageCache.init(
negativeCacheDuration: const Duration(minutes: 10),
negativeCacheStatusCodes: const {404},
);
Expired entries are still refreshed when possible. If refresh fails and stale bytes exist, the engine can return the stale bytes instead of breaking the UI.
Testing #
The engine is built around public contracts, so tests can avoid real HTTP and disk:
final manager = ImageCacheManager(
l1: FakeStore(),
l2: FakeStore(),
fetchers: [FakeFetcher()],
keyGenerator: ValidationKeyGenerator(),
);
The package test suite covers memory/disk hits, stale fallback, negative cache, SVG rendering, invalid bytes, headers, cleanup, compression, and the example app.
flutter test
flutter test -d chrome test/cached_image_widget_test.dart
Comparison #
| Package | Raster cache | SVG | Custom stores/fetchers | Stale fallback | Negative cache |
|---|---|---|---|---|---|
all_image_cache |
Yes | Yes, via CachedSvgImage |
Yes | Yes | Opt-in |
cached_network_image |
Yes | No built-in SVG widget | Cache-manager based | Partial/stale patterns vary | No built-in negative cache |
cached_network_svg_image |
SVG-focused | Yes | Narrower API | Limited | No built-in negative cache |
When to use it #
Use all_image_cache when your app needs a single image cache layer for network images, local files, memory bytes, SVG assets, authenticated URLs, custom storage/fetching, and testable behavior.
Use a simpler widget if you only need Image.network with no persistence, no custom cache behavior, and no test doubles.
Documentation #
- Example app
- API reference
Contributors #
Made with contrib.rocks.
How to contribute #
Contributions are welcome. Read CONTRIBUTING.md to get started.
License #
MIT