pub repository
mirror.p-hatan.comcached_network_image_ce
4.13.1Community Edition Flutter library to load and cache network images. Can also be used with placeholder and error widgets.
Cached in Iran · upstream_checksum
Readme
Cached Network Image (Community Edition)
A Flutter library to show images from the internet and keep them in the cache directory.
This is the actively maintained, high-performance community fork of cached_network_image, powered by hive_ce instead of sqflite for up to 8x faster cache reads and smoother scrolling.
For the full pitch, architecture diagram, benchmarks, and package comparison table, see the repo README. This page is the complete API reference.
Why this fork exists
The original cached_network_image package by Baseflow is a titan in the Flutter ecosystem, used by millions. However, it has been effectively unmaintained since August 2024, leaving over 300 issues unresolved, including critical memory leaks and scroll performance bugs.
As the Flutter ecosystem evolved, the original architecture began to show its age. It relied on sqflite for cache management: a heavy, SQL-based solution that requires platform channels to communicate with native code. For a simple task like "checking if an image exists," this overhead caused UI jank in heavy lists.
We created the Community Edition (_ce) to fix this. We didn't just fork it to merge dependabot PRs. We re-engineered the caching layer.
The architectural shift: SQLite vs. Hive
We replaced the heavy sqflite dependency with hive_ce.
- Old way (
sqflite): serialized data → Platform Channel → Java/Obj-C → SQLite → Disk. Slow, blocking. - New way (
hive_ce): Dart Memory → Direct Disk Access. Instant, non-blocking.
The result: zero-jank scrolling.
Benchmarks
We benchmarked the cache metadata operations (checking, writing, and deleting cache entries) on an iPhone Simulator. The results speak for themselves:
| Operation | Payload Size | Original (sqflite) |
CE (hive_ce) |
Improvement |
|---|---|---|---|---|
| Read (Hit Check) | 10 KB | 16 ms | 2 ms | 8.00x faster |
| Write (New Image) | 10 KB | 116 ms | 29 ms | 4.00x faster |
| Delete (Cleanup) | 10 KB | 55 ms | 19 ms | 2.89x faster |
| Read (Large) | 1 MB | 8 ms | 1 ms | 8.00x faster |
Note: "Read" is the most critical operation for scrolling performance, as every list item checks the cache before rendering.
Features
It's a drop-in replacement, about 99% API compatible with the original package. Cache lookups go through hive_ce, so they're fast and non-blocking. Unlike the original package, it caches images fully and persistently on the web via IndexedDB, and avoids RAM spikes by decoding at native image sizes instead of full resolution. HTTP and cache interceptor chains let you add auth headers, inject synthetic responses, or skip caching selectively, all without forking the package. It's still getting regular updates and bug fixes too.
Installation
Install with:
flutter pub add cached_network_image_ce
How to use
The API is identical to the original package. You can use CachedNetworkImage directly or via ImageProvider. Both approaches are fully supported with persistent IndexedDB caching on the web platform out of the box.
Basic Usage with Placeholder
import 'package:cached_network_image_ce/cached_network_image.dart';
CachedNetworkImage(
imageUrl: 'https://via.placeholder.com/350x150',
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
With Progress Indicator
CachedNetworkImage(
imageUrl: 'https://via.placeholder.com/350x150',
progressIndicatorBuilder: (context, url, downloadProgress) =>
CircularProgressIndicator(value: downloadProgress.progress),
errorWidget: (context, url, error) => Icon(Icons.error),
),
Advanced Usage (ImageBuilder)
Use this when you need an ImageProvider for things like DecorationImage:
CachedNetworkImage(
imageUrl: 'https://via.placeholder.com/200x150',
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(Colors.red, BlendMode.colorBurn),
),
),
),
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
Direct ImageProvider Usage
Image(image: CachedNetworkImageProvider(url))
Network Timeouts (DefaultCacheManager)
You can configure network timeouts at the cache manager level using
ConnectionParameters.
final cacheManager = DefaultCacheManager(
connectionParameters: ConnectionParameters(
connectionTimeout: const Duration(seconds: 10),
requestTimeout: const Duration(seconds: 30),
),
);
CachedNetworkImage(
imageUrl: 'https://example.com/image.jpg',
cacheManager: cacheManager,
errorBuilder: (context, url, error) => const Icon(Icons.error),
)
Timeout behavior:
connectionTimeout: max time waiting for response headers.requestTimeout: inactivity timeout while streaming response bytes.
Both fields are optional and nullable. If connectionParameters is not
provided, existing behavior is preserved (no timeout is applied).
On Flutter Web, timeout settings apply when using
ImageRenderMethodForWeb.HttpGet. The HtmlImage render method uses the
browser image pipeline and bypasses the cache manager HTTP path.
Cache and Metadata Directories
On native IO targets, cached image files and Hive metadata can use separate base directories.
final cacheManager = DefaultCacheManager(
cacheDirectoryProvider: getTemporaryDirectory,
metadataDirectoryProvider: getApplicationSupportDirectory,
);
If metadataDirectoryProvider is omitted, metadata stays under the cache
directory:
<cacheBase>/cached_network_image_ce/
<cacheBase>/cached_network_image_ce/hive/
Web Platform Headers Support: Custom headers (like Authorization) are
only supported with ImageRenderMethodForWeb.HttpGet. The default
HtmlImage render method does not support custom headers. If you need to
send headers to authenticate image requests on Web, you must explicitly set:
CachedNetworkImage(
imageUrl: 'https://api.example.com/image.jpg',
httpHeaders: {'Authorization': 'Bearer token'},
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
),
Note: Using HttpGet on Web disables the browser's default image caching
mechanisms, so images are cached via the cache_manager instead.
HTTP Interceptors
Intercept and modify HTTP requests, responses, and errors before they reach the cache layer. Useful for adding auth headers, logging, retrying, or short-circuiting with a synthetic response.
import 'package:cached_network_image_ce/cached_network_image.dart';
class AuthInterceptor extends HttpInterceptor {
final String token;
const AuthInterceptor(this.token);
@override
void onRequest(HttpRequestData request, HttpRequestHandler handler) {
request.headers['Authorization'] = 'Bearer $token';
handler.next(request); // pass (possibly mutated) request to next interceptor
}
}
final manager = DefaultCacheManager(
httpInterceptors: [AuthInterceptor('my-token')],
);
Each hook must call exactly one of handler.next, handler.resolve, or handler.reject.
Failing to call any will stall the pipeline permanently.
| Hook | Trigger | Handler methods |
|---|---|---|
onRequest |
Before HTTP call | next(request) · resolve(response) · reject(error) |
onResponse |
After HTTP response received | next(response) · resolve(response) · reject(error) |
onError |
HTTP call threw | next(error, st) · resolve(response) · reject(error) |
Cache Interceptors
Intercept cache hit, miss, and store events to control how entries are read from and written to the cache index. Only available on native IO targets (Android, iOS, macOS, Linux, Windows); not available on web.
import 'package:cached_network_image_ce/cached_network_image.dart';
// Reject storage for specific URLs (e.g. private/sensitive images).
class PrivateImageInterceptor extends CacheInterceptor {
@override
void onStore(CacheStoreData data, CacheStoreHandler handler) {
if (data.url.contains('/private/')) {
handler.reject(); // skip writing to Hive; file is delivered then deleted
} else {
handler.next(data);
}
}
}
final manager = DefaultCacheManager(
cacheInterceptors: [PrivateImageInterceptor()],
);
| Hook | Trigger | Handler methods |
|---|---|---|
onHit |
Cached entry found and valid | next(data) · resolve(fileInfo) · reject (force re-download) |
onMiss |
No cached entry found | next(data) · resolve(fileInfo) (skip download entirely) |
onStore |
After download, before writing metadata | next(data) · reject (skip persisting; cache file deleted) |
When onStore rejects, the downloaded file is copied to a system-temp location, the
cache-directory copy is deleted (no orphan), and the temp copy is yielded to the caller for
this request only.
Pre-caching Images
Download and cache images before they appear on screen, so navigation
feels instant. preCache reuses the same cache manager and key logic as
the widget.
// Warm the cache ahead of time (e.g. in initState or a splash screen).
await CachedNetworkImage.preCache(
imageUrl: 'https://example.com/hero.jpg',
);
// Later, the widget loads from cache with no network wait.
CachedNetworkImage(imageUrl: 'https://example.com/hero.jpg')
All parameters are optional except imageUrl:
await CachedNetworkImage.preCache(
imageUrl: 'https://example.com/hero.jpg',
cacheKey: 'hero',
headers: {'Authorization': 'Bearer token'},
cacheManager: myCustomCacheManager,
maxWidthDiskCache: 800,
maxHeightDiskCache: 600,
timeout: const Duration(seconds: 10),
);
Returns a FileInfo with the cached file path, expiry, and source. Waits
for an expired cache entry to finish refreshing before returning, and
throws a StateError instead of returning a stale file if that refresh
fails. timeout, if given, throws a TimeoutException when exceeded but
does not cancel the underlying download. maxWidthDiskCache /
maxHeightDiskCache throw an ArgumentError when cacheManager isn't an
ImageCacheManager.
Animated Images (GIF)
Set animate: false to show only the first frame of a multi-frame image.
The remaining frames are never decoded.
CachedNetworkImage(
imageUrl: 'https://example.com/animation.gif',
animate: false,
)
Only the frame callbacks and the getNextFrame() calls for the remaining
frames are skipped. The whole file is still downloaded, cached, read back
and decoded into a codec, so animate: false is not a way to save bandwidth
or memory on large GIFs.
animate is part of the image provider key, so toggling it at runtime
resolves a different image stream. The widget paints nothing while that
stream resolves, and which frame it starts on depends on whether its key is
still held by the ImageCache — an animation that played before is likely
to resume where it left off rather than restart. To pause and resume in
place without changing the key, wrap the widget in a TickerMode instead:
TickerMode(
enabled: !paused,
child: CachedNetworkImage(imageUrl: 'https://example.com/animation.gif'),
)
MediaQueryData.disableAnimations pauses animated images the same way.
Both need Flutter 3.41 or newer to show the first frame when the image
loads while already paused (flutter/flutter#176492);
on older versions a widget that mounts paused stays blank until it resumes.
animate: false has no such requirement and works on every supported
Flutter version.
On the web this only applies to ImageRenderMethodForWeb.HttpGet. The
default, HtmlImage, decodes through an <img> element whose codec reports
a single frame (HtmlImageElementCodec.frameCount => 1 in the Flutter web
engine), so animated images never play there and there is nothing for
animate or TickerMode to stop:
CachedNetworkImage(
imageUrl: 'https://example.com/animation.gif',
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
)
If you need full playback control (play, pause, seek), read the bytes from
the cache manager yourself (DefaultCacheManager().getFileStream(url), or
DefaultCacheManagerWeb on the web) and hand them to a package such as
gif_view. CachedNetworkImageProvider cannot do this: every load path it
offers returns an ImageStreamCompleter, never the bytes.
Unsupported Image Formats (SVG, JXL, AVIF, HEIC, ...)
Flutter's built-in image codec can't decode every format. SVG never works
(it's not a raster format), and some raster formats (JXL, AVIF, HEIC, ...) may
fail depending on platform/OS codec support. When CachedNetworkImage detects
SVG bytes, or the codec otherwise fails to decode the cached bytes, it throws
an UnsupportedImageFormatException instead of leaving you with an opaque
decode error. Use the unsupportedImageBuilder callback to render the raw
bytes with a format-specific package of your choice, for example
flutter_svg for SVG, or
flutter_avif for AVIF:
Before using SvgPicture.memory, add flutter_svg to pubspec.yaml
(dependencies: flutter_svg: ^2.2.1) and import
package:flutter_svg/flutter_svg.dart.
CachedNetworkImage(
imageUrl: 'https://example.com/image.svg',
unsupportedImageBuilder: (context, url, bytes) {
// `bytes` are the already-cached file bytes.
return SvgPicture.memory(bytes); // from flutter_svg
},
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
The image is still downloaded and cached normally; only the rendering
path is different. If unsupportedImageBuilder is not set, the error falls
through to errorWidget with an UnsupportedImageFormatException.
SVG is detected ahead of time, so its exception carries
detectedFormat: 'svg'. Any other codec decode failure (JXL, AVIF, HEIC, or a
genuinely corrupt file) is only caught once decoding is actually attempted, so
detectedFormat is null in that case. Check the bytes yourself (e.g. magic
numbers) if you need to distinguish which format/decoder to use inside
unsupportedImageBuilder.
Web caveat: this whole mechanism requires the raw cached bytes, so it only
works with ImageRenderMethodForWeb.HttpGet. The default HtmlImage render
method hands the URL straight to the browser's native image pipeline and never
has bytes to inspect, so a decode failure there falls straight through to
errorBuilder/errorWidget as a plain error, not an
UnsupportedImageFormatException.
FAQ
Q: Will I lose my users' existing cache if I migrate? A: Yes. Because we switched the storage engine from SQLite to Hive, the old cache files will be ignored. Users will re-download images once as they browse. This is a one-time migration cost for a permanent performance gain.
Q: My app crashes/pauses on errors?
A: In Debug mode, Flutter may pause on exceptions even if they are caught. This is expected behavior for network errors (404s). In Release mode, these are handled silently by the errorWidget.
Q: Why is web caching slower or using Hive for image bytes?
A: On Mobile & Desktop (IO), this package stores image bytes directly on the native file system and uses Hive only for metadata. The Web platform, however, lacks a native file system. So for web we use hive_ce to store both metadata and the actual image bytes in IndexedDB. Serializing large byte arrays in and out of IndexedDB introduces overhead that isn't present on IO.
Alternative: If persistent caching across sessions isn't critical for your web users, consider conditionally using the standard Image.network on the web, which relies on the browser's built-in memory/HTTP caching to achieve faster decoding.
Contributing
We welcome contributions! If you want to help maintain this essential package, please check the CONTRIBUTING.md.
License
This project is licensed under the MIT License.
Changelog
[4.13.1] - 2026-09-26
- Fix: Animated images played slower than their frame durations, e.g. 20ms GIF frames at 60% speed on a 60Hz display, because
MultiImageStreamCompleterrounded every frame up to the next vsync. Frames now follow their durations on the wall-clock timeline, skipping frames that are already late when decoding is fast enough to catch up (flutter/flutter#24804).
[4.13.0] - 2026-09-26
- Feature:
maxWidthDiskCache/maxHeightDiskCachenow resize WebP images on disk. Before, WebP files were stored at full size. As with JPEG and PNG, this applies when the URL path ends in.webp. Requested in issue #78. - Fix: Animated images (animated WebP, APNG) are no longer resized on disk. Resizing keeps only the first frame, so they are cached as the original file and keep animating.
[4.12.0] - 2026-09-08
- Feature: Added
animatetoCachedNetworkImageandCachedNetworkImageProvider(defaulttrue). Withanimate: falsea multi-frame image such as a GIF shows its first frame and stops there, without decoding the rest.animateis part of the provider key, so toggling it at runtime resolves a different image stream: the widget paints nothing while that stream resolves, and which frame it starts on depends on what theImageCachestill holds. Wrap the widget in aTickerModeto pause and resume an animation in place. Requested in issue #21. - Fix:
CachedNetworkImage.evictFromCachenow forwardscacheKeyto the provider it evicts and clears both theanimate: trueandanimate: falseentries, so the in-memoryImageCacheeviction is no longer a silent no-op for images rendered with acacheKeyor withanimate: false.
[4.11.1] - 2026-09-08
- Fix: Images turned black on web after the widget was scrolled out of view and back.
MultiImageStreamCompleterre-decoded the codec on every 0→1 listener transition; for a single-frame image on CanvasKit that produces a second lazyui.Imagesharing one<img>element, and emitting it disposes the previous image, which clears that element'ssrc. The already decoded frame is now handed to the returning listener instead. Animated images still resume decoding. Reported by @tranhuudang (issue #67). - Fix: The completer handed the codec's own
ui.ImagetoImageInfoinstead of a clone and never disposed_nextFrame, so every decode that was abandoned (listener dropped mid-decode) or superseded leaked aui.Image. Frames are now cloned intoImageInfoand the decoded frame is disposed once handed over, matching the framework'sMultiFrameImageStreamCompleter. That is also the ownership bug behind the black image above:setImagedisposing the previousImageInfono longer releases a handle the codec's decoded frame still owns. - Fix: A frame could be emitted under a codec that had already replaced the one it was decoded from.
_decodeNextFrameAndSchedulenow captures its codec and discards the frame if the codec changed during the await, instead of evaluatingframeCountagainst the new codec — which could terminate a running animation and mis-count the new codec's frames. - Fix: Adding a listener while a decode was already in flight started a second, concurrent decode of the same codec, so two frames could be emitted and dispose each other's image.
addListenerno longer starts a decode while one is pending. - Fix: A null-check crash when a replacement codec arrived between an animated frame being decoded and its scheduled app-frame callback running, or when a listener removed and re-added itself from the
setImagecallback. Both released the pending frame while_handleAppFramewas still reading it. The callback now takes the frame before notifying listeners and returns quietly if the frame it was scheduled for is already gone, and decoding a codec that already has a frame in flight is a no-op. - Fix: Replaced codecs are now disposed instead of dropped, so a cache hit followed by a network refresh no longer retains the outgoing decoder for the life of the completer. A codec replaced while one of its frames is still decoding is disposed by that decode when it returns, since disposing it earlier would fail the pending
getNextFrame().
[4.11.0] - 2026-09-01
- Feature: Added
CachedNetworkImage.preCache()static method for downloading and caching images without rendering them. Useful for warming the cache before navigation. Supports optionalcacheKey,headers, customcacheManager, disk-resize parameters (maxWidthDiskCache,maxHeightDiskCache), and an optionaltimeout. Throws aStateErrorinstead of silently returning a stale file when refreshing an expired cache entry fails, and anArgumentError(not just anassert) when resize parameters are used with aCacheManagerthat isn't anImageCacheManager.
[4.10.1] - 2026-08-26
- Fix:
PathNotFoundExceptionwhen the background cleanup sweep deleted a cached file aftergetFileFromCachehad already handed out itsFileInfobut before the image was read. The sweep starts unawaited during initialization, so on cold start every first-frame load raced it. A cached file that disappears mid-read now falls back to a fresh download instead of throwing. Applies to the resize path too, which reads the separately-evictable original entry. - Fix:
getImageFileremoved its in-flight resize entry only after its stream completed, so abandoning that stream left every later call for the same key waiting on a stream that had already finished, and no image was ever delivered. - Fix:
putFilenow awaits its Hive metadata write instead of returning while the write is still unsequenced. - Behaviour change: The cleanup sweep skips entries served within the last 30 seconds, so an image still being loaded is not evicted out from under its reader. Skipped entries lose their place in the eviction order but not the size budget, so
maxNrOfCacheObjectsis still honoured.
reported by @aycasecr — thanks! (PR #62)
[4.10.0] - 2026-07-30
- Performance:
DefaultCacheManagernow reuses a single HTTP client across downloads instead of creating and closing one per request, so connections can be kept alive between images. - Fix: A connection timeout now aborts the in-flight request instead of leaving it running in the background.
- Fix:
dispose()closes the reused client. Downloads started after disposal create their own client, which is closed once its last response is released. - Behaviour change:
dispose()called while a download is in flight now aborts that download; previously each download owned its client and could outlivedispose(). - Behaviour change: An
onResponseinterceptor that replaces the response must not derive the replacement body from the original response's stream — the original body is now canceled as soon as it is replaced, to release its connection.
contributed by @Chlx42 — thanks! (PR #58)
[4.9.1] - 2026-07-23
- Fix: Codec decode failures (e.g. JXL, or AVIF/HEIC on platforms without native support) now route to
unsupportedImageBuilderinstead oferrorBuilder. Previously only pre-detected formats (SVG) were routed this way viaUnsupportedImageFormatException; any other codec decode failure fell through as a generic, untyped error.
[4.9.0] - 2026-06-19
- Feature: Added
metadataDirectoryProvidertoDefaultCacheManagerso Hive metadata can be stored separately from cached image files on IO platforms. - Fix: Isolate the orphan-file cleanup sweep per metadata directory, so two
DefaultCacheManagerinstances sharing acacheDirectoryProviderbut differentmetadataDirectoryProviderno longer delete each other's files.dispose()now awaits any in-flight sweep instead of racing it.
[4.8.0] - 2026-06-16
- Feature: Added LRU cache cleanup support to
DefaultCacheManager.- New
CleanupStrategyabstraction controls eviction order when the cache exceedsmaxNrOfCacheObjects. TtlCleanupStrategy— evicts soonest-to-expire entries first. Matches prior behaviour and remains the default.LruCleanupStrategy— evicts least-recently-used entries first, based on a newtouchedAttimestamp updated on every cache hit.CacheEntryMetadatagains a nullabletouchedAtfield; legacy entries without it fall back tovalidTillviaeffectiveTouchedAt.- Pass a strategy via the new
cleanupStrategyparameter onDefaultCacheManager, or implementCleanupStrategyfor a custom eviction policy.
- New
[4.7.0] - 2026-06-10
- Feature: Added HTTP and cache interceptor support to
DefaultCacheManager.HttpInterceptor— intercept, mutate, or short-circuit HTTP requests, responses, and errors before they reach the cache layer.CacheInterceptor— intercept cache hit, miss, and store events. Reject a hit to force re-download; resolve a miss to inject a synthetic file; reject a store to skip writing metadata to Hive.- Pass interceptors via the new
httpInterceptorsandcacheInterceptorsparameters onDefaultCacheManager. CacheInterceptorand its handler types are only available on native IO targets; a no-op stub is exported for web.- Full test coverage for all interceptor chain paths.
[4.6.4] - 2026-03-24
- Fix: Resolve
HiveErrorcrashes caused by URL string keys exceeding 255 characters. Long cache keys are now automatically hashed using SHA-256 to remain under Hive's 255-character length limit.
[4.6.3] - 2026-03-15
- Fix: Handle exceptions when closing the Hive cache box and Hive instance during
dispose(). (PR #17)PathNotFoundException(e.g. when the cache directory was deleted before dispose) is now silently swallowed so callers can dispose without wrapping in try-catch.
- Feat: Ensure the cache directory exists before any file read/write operation. (PR #17)
- Prevents
PathNotFoundExceptionon first use when the OS or test harness removes the temp directory between initialisation and the first cache put/get.
- Prevents
- Added regression tests for cache-directory resilience and for safe disposal after
emptyCache(). (PR #17)
[4.6.2] - 2026-03-04
- Fix: Handle Hive box corruption gracefully during cache initialization.
- When
openBoxencounters a corrupted box with unknown typeIds (e.g., from removed adapters), catchHiveError, safely delete the box, and retry initialization. - Cleans up orphaned cache files after box recovery to prevent stale data.
- Regression tests added for box corruption recovery on both IO and web platforms.
- Issue #12: Fixes production crash "HiveError: Cannot read, unknown typeId" reported via Firebase Crashlytics.
- When
[4.6.1] - 2026-03-04
- Fix: Re-export
ConnectionParametersfrom the maincached_network_image_cebarrel file so it is accessible without a separatecached_network_image_platform_interface_ceimport. - Fix: Added missing
connectionParametersparameter to the stubDefaultCacheManagerfor unsupported platforms. - Added example demonstrating
DefaultCacheManagerwithConnectionParameters.
[4.6.0] - 2026-03-03
- Feature: Added optional HTTP timeout support via
ConnectionParametersonDefaultCacheManager.connectionTimeoutlimits time waiting for response headers.requestTimeoutapplies an inactivity timeout while streaming response bytes.- Existing behavior is preserved when
connectionParametersis not provided.
- Added tests for timeout behavior and client cleanup on timeout.
[4.5.0] - 2026-03-02
- Feature: Added web platform support. The package can now be used in Flutter web apps.
- Web caching uses Hive CE backed by IndexedDB — no new dependencies needed.
- Image bytes and metadata are stored in Hive boxes on web instead of the file system.
- Disk-based image resizing is skipped on web (originals are cached as-is).
- The
DefaultCacheManageris now conditionally imported per platform (IO/web).
[4.4.0] - 2026-02-27
- Feature: Skip placeholder and fade animations when images are loaded from disk cache. Cached images now appear instantly without unnecessary visual flicker.
- Added
disablePlaceholderOnCacheHitparameter (defaulttrue) to opt out of this behavior. CachedNetworkImageis now aStatefulWidgetto support async cache pre-checking.
[4.3.0] - 2026-02-26
- Feature/Deprecation: Added
errorBuildertoCachedNetworkImageandCachedImageWidget, which aligns with Flutter's standardImageErrorWidgetBuilder. The olderrorWidgetproperty is now deprecated. - Fix: Resolved a memory leak where
errorListenerwould preventCachedNetworkImagefrom being garbage collected. UsesaddEphemeralErrorListeneron Flutter >= 3.16.
[4.2.0] - 2026-02-23
- Feature: Added SVG support via new
unsupportedImageBuildercallback- New
UnsupportedImageFormatExceptionthrown when image format is not supported by Flutter's standard codec - New
ImageFormatDetectorutility with content sniffing for SVG detection - Images are still cached normally; only rendering path differs
- Example app updated with SVG demo using
flutter_svg - 24 new tests added (18 format detection + 6 widget integration)
- See README for usage example
- New
[4.1.1] - 2026-02-20
- Fix: Removed global
Hive.init()usage fromDefaultCacheManagerto avoid conflicts with host app Hive initialization - Fix: Added initialization synchronization in
DefaultCacheManagerto prevent parallel cold-start race conditions - Fix: Switched cache metadata box opening to explicit
openBox(path: ...)on a private Hive instance for reliable isolation - Feature: Added optional
cacheDirectoryProviderparameter toDefaultCacheManagerso apps can control cache storage location - Tests: Added regression tests for Hive init conflicts, concurrent initialization races, and cache directory resilience scenarios
[4.1.0] - 2026-02-19
- Feature: Added
httpClientFactoryparameter toDefaultCacheManagerfor HTTP client dependency injection, enabling easy mocking in tests - Refactor: Replaced raw
Map<String, dynamic>with typedCacheEntryMetadataclass for all cache metadata operations - Tests: Comprehensive test coverage (131 tests, 86% coverage)
DefaultCacheManager: HTTP download success/errors, progress reporting, header forwarding, cache hit/miss/stale behavior, cleanup logic (31 tests)- Leak tests: StreamController closure,
http.Clientcleanup, file sink closure,ImageLoaderchunkEvents,MultiImageStreamCompleterdisposal, Hive box lifecycle (19 tests) ImageLoader,CachedNetworkImageProvider,CacheEntryMetadatacoverage
- Fix: Resolved analyzer warnings across all packages
[4.0.1] - 2026-02-19
- Added
repositoryfield for pub.dev source code display - Updated README with benchmarks and architectural details
- Updated dependencies to
_cesuffixed packages
[3.4.1] - 2024-08-13
- Target js_interop for Wasm support
[3.4.0] - 2024-04-10
- Change how errors are reported by ImageLoader. Emitting errors as streams instead of re-throwing.
- Improved debug console messages
- Update dependencies
- added static field defaultCacheManager to CachedNetworkImageProvider
- Expose scale of CachedNetworkImageProvider on CachedNetworkImage
[3.3.1] - 2023-12-31
- Adding an errorListener prevents automatic reporting to global error handler.
[3.3.0] - 2023-09-25
- Add error to ErrorListener
- Update to Dart 3
- Remove
load, useloadImageinsteadloadBuffer
Minor code clean-ups:
- Add topics in pubspec
- Specify types
- Update example
[3.2.3] - 2022-11-25
- Correctly dispose image stream handler
[3.2.2] - 2022-08-31
- loadBuffer is added and used instead of load
[3.2.1] - 2022-05-16
- Update to Flutter 3
[3.2.0] - 2021-11-29
- Add option to set the log level of the cache manager, for example:
CachedNetworkImage.logLevel = CacheManagerLogLevel.debug;
- Update cache manager dependency.
[3.1.0+1] - 2021-11-04
- Update Readme
[3.1.0] - 2021-07-16
- Separate Web and IO implementations
[3.0.0] - 2021-03-27
- Migrate to null safety
- Fix "Cannot clone a disposed image" error
- Update dependencies.
[3.0.0-nullsafety] - 2021-01-02
- Migrate to null safety
[2.5.1] - 2021-03-09
- Update dependencies
[2.5.0] - 2020-12-22
- Add support for resizing images in disk cache.
CachedNetworkImage(
maxHeightDiskCache: 200,
imageUrl: 'https://via.placeholder.com/3000x2000',
);
[2.4.1] - 2020-12-01
- Fix a bug that an image is disposed when it shouldn't.
[2.4.0] - 2020-11-30
- Added support for a cache key which is different from the image url.
[2.3.3] - 2020-10-16
- Support for flutter_cache_manager 2.x.x.
[2.3.2] - 2020-09-10
- Fixed placeholders and error widgets, those are not always centered anymore.
- Evict an image from ImageCache if image fails to load.
- Added method to evict an image from memory and disk cache.
[2.3.1] - 2020-08-25
- Fixed fading when the image has no placeholder or progress indicator.
[2.3.0] - 2020-08-25
- Improved image loading by using OctoImage. OctoImage uses the native callbacks of the ImageProvider instead of loading the file when the ImageWidget is build the first time.
- Set minimal Flutter version to 1.20.0; first compatible stable version.
- Added choice for rendering of images on web. Defaults to standard HTML ImageElement, but gives the option to use a custom HTTP Get for headers and skia support.
- Use a MultiImageStreamCompleter for when an image that is available in the cache is updated.
[2.3.0-rc] - 2020-06-20
- Added choice for rendering of images on web. Defaults to standard HTML ImageElement, but gives the option to use a custom HTTP Get for headers and skia support.
- Use a MultiImageStreamCompleter for when an image that is available in the cache is updated.
- Increase minimal version of Flutter to 1.19.0-2.0.pre (currently requires Beta) due to an error listener bug.
[2.3.0-beta.1] - 2020-05-28
- Improved web support: support for headers and skia.
[2.3.0-beta] - 2020-05-20
- Rewrote image widget by using OctoImage.
[2.2.0+1] - 2020-05-05
- Fix ImageProvider not using provided headers.
[2.2.0] - 2020-04-30
- Upgrades on CachedNetworkImageProvider:
- Support for download progress.
- Basic web support (no caching).
[2.1.0+1] - 2020-04-10
- Update minimal Dart sdk version
[2.1.0] - 2020-04-10
- Update CacheManager
- Added option for progress indicator
[2.0.0] - 2019-12-31
- Public release of 2.0 version
[2.0.0-rc.1] - 2019-11-04
- Revert scaling of image due to issues with BoxFit.
[2.0.0-rc] - 2019-10-17
- BREAKING CHANGE: Compatibility for breaking change in Flutter 1.10.15
[1.1.3] - 2019-11-04
- Revert scaling of image due to issues with BoxFit.
[1.1.2+1] - 2019-10-17
- Fix for widgets declared with infinite size.
[1.1.2] - 2019-10-16
- Add filterQuality property.
- Scale image to size when showing in widget.
- Better error handling.
- Fix for useOldImageOnUrlChange.
- Update cache manager to 1.1.2.
[1.1.1] - 2019-07-23
- Updated cache manager for error handling fix
[1.1.0] - 2019-07-13
- Improved performance
- Keep fetched files in sync with filemanager.
- Better error handling.
- Added extra example to show the imageBuilder
[1.0.0] - 2019-06-27
- Updated dependencies
[0.8.0] - 2019-05-06
- Fixed compile error on informationCollector by temporarily disabling it.
[0.7.0] - 2019-03-06
- BREAKING CHANGE: Renamed ErrorWidgetBuilder to LoadingErrorWidgetBuilder
- LoadingErrorWidgetBuilder returns an Object instead of an Exception
- Fixed BoxFit to also work when size is not defined
[0.6.2] - 2019-02-27
- Added option to blend image with color
- Added option in CacheManager to clear the cache
[0.6.1] - 2019-02-25 BREAKING CHANGES
- No longer assume infinite size.
[0.6.0] - 2019-02-18 BREAKING CHANGES
- Breaking changes in API and behaviour
- Very much improved though
- Adapted for new cache manager library
- Completely rewritten image view
- Now using builders for placeholder and error widgets
- Added optional builder to customize the image
[0.5.1] - 2018-11-19
- Fixed error throwing
[0.5.0] - 2018-10-13
- Updated cache manager for http 0.12.0
[0.4.2] - 2018-08-30
- Updated cache manager dependency
[0.4.1] - 2018-04-27
- Improved error handling when a file could not be loaded.
[0.4.0] - 2018-04-14
- Added optional headers.
- Changed to Dart 2.0
- Fixed bug when updating widget with new url
[0.3.0] - 2018-02-09
- Added CachedNetworkImage with placeholder and error widgets.
[0.2.1] - 2018-01-08
- Moved from OneFrameImageStreamCompleter to MultiFrameImageStreamCompleter.
- Updated CacheManager dependency for critical bug fix.
[0.2.0] - 2017-12-29
- Breaking change Removed CachedNetworkImage. From now on only the ImageProvider is supported. For a placeholder use
FadeInImage. See also "Fallback for Network Images". - Moved CacheManager to a separate library for a more generic purpose.
[0.1.0] - 2017-12-21
- Breaking change. Upgraded to Gradle 4.1 and Android Studio Gradle plugin 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in order to use this version. Instructions can be found here.
[0.0.2] - 10 December 2017
Added an ImageProvider and improved documentation
[0.0.1] - 2 December 2017
Initial release, should be polished
Installing
export PUB_HOSTED_URL=https://pub.mirror.p-hatan.com
flutter pub add cached_network_image_cepubspec.yaml
name: cached_network_image_ce
description: Community Edition Flutter library to load and cache network images.
Can also be used with placeholder and error widgets.
homepage: https://github.com/Erengun/flutter_cached_network_image_ce
repository: https://github.com/Erengun/flutter_cached_network_image_ce/tree/develop/cached_network_image
topics:
- cache
- image
- network-image
version: 4.13.1
environment:
sdk: ^3.0.0
flutter: '>=3.10.0'
dependencies:
cached_network_image_platform_interface_ce: ^5.2.0
cached_network_image_web_ce: ^2.1.0
clock: ^1.1.1
crypto: ^3.0.0
file: '>=7.0.0 <8.0.0'
flutter:
sdk: flutter
hive_ce: ^2.0.0
http: ^1.6.0
meta: ^1.9.0
octo_image: ^2.1.0
path: ^1.8.0
path_provider: ^2.0.0
dev_dependencies:
flutter_lints: ^4.0.0
flutter_test:
sdk: flutter
mocktail: ^1.0.4
Version history
| Version | Published | Archive | SHA-256 |
|---|---|---|---|
| 4.0.0 | 2026-02-19T10:06:45.468665Z | Cached | 5b102eeb7a0278f807e2a642d8efa7d206e13ea7792e24afdb7670e59e5d62ee |
| 4.0.1 | 2026-02-19T10:19:04.924300Z | Cached | bede5b1e74e8c99be0ee867e9e35d5fc632b09b6cf18ab74a94f6e0b2e8351a8 |
| 4.1.0 | 2026-02-20T08:25:51.541871Z | Cached | 78e06dad3ea819da22699a369a49b82f5cbb49661e192ad24bd7b2c5a1c2d970 |
| 4.1.1 | 2026-02-20T18:43:17.930526Z | Cached | 167b590c7e8e2e1738dc92fcdee822ca4b8ad1c7b71738adad938bbb3d614da9 |
| 4.2.0 | 2026-02-23T12:00:38.847517Z | Cached | 9a868c4a13dae1a17df19e48e26ba5989ce3545ebf226abf35299fd12d70c5d6 |
| 4.3.0 | 2026-02-26T09:11:02.636611Z | Cached | 9892eb9051c8dc25bf63c49a34a058fe33fcf1503099cab4cd9015b5c760df4c |
| 4.4.0 | 2026-02-27T08:08:16.390260Z | Cached | f2d9ac386a7bd4f5b8011cc4a6e77a2ef3bd18d42e3ef8463bdfb6057c3a0a93 |
| 4.5.0 | 2026-03-02T20:23:27.949795Z | Cached | 57e6434e016b318736d1f0e1316a1f204a6127d03a25af44218b643d20b4fc1c |
| 4.6.0 | 2026-03-03T12:04:43.533531Z | Cached | 7708ac41f0e3692066d682e384d9a1a5b647c514a981982bf0c8522f5e8845ba |
| 4.6.1 | 2026-03-04T11:12:13.036549Z | Cached | 4084b07d2db6f73861fd190a559d8afceb29a7ed750017108d93414957befcb4 |
| 4.6.2 | 2026-03-04T11:51:15.177423Z | Cached | c95695c9b4a2ace82f0a75789428a746bc2af789974a7b6b5e96e1bd0eb55301 |
| 4.6.3 | 2026-03-15T13:33:04.926599Z | Cached | ee8e3631a9ad073daa803a45d4d638020f66c320a225567a0aed4b1ca20da1ae |
| 4.6.4 | 2026-03-24T12:41:08.850749Z | Cached | d4701fbbdf508de831e847fd1d49c644ffa6191c6018c416ab6f66bbe1ad5fff |
| 4.7.0 | 2026-06-10T14:27:24.992731Z | Cached | da6edbc8d5ae7361f680062795a8561c65622cbbd02bbd50b9291f188677bded |
| 4.8.0 | 2026-06-17T09:05:38.128132Z | Cached | f755f124fd48da7a9f24e4ec825d6b11a60602e956ac9467e974e88554375181 |
| 4.9.0 | 2026-06-20T12:42:03.115888Z | Cached | 9c61372fecd5f6ac6aaa66fa6808b4c303b8574875e853a0916116bf2fae6840 |
| 4.9.1 | 2026-07-29T06:59:22.490010Z | Cached | 2d76205eb8cbe8acd8d000357017231bc2d3a056ccec5201d72a589808d9861b |
| 4.10.0 | 2026-07-30T15:46:25.561343Z | Cached | 974594da61403c25849107ce6df0a31034f8a660612dc89c582b70caa03e6e98 |
| 4.10.1 | 2026-08-26T07:26:40.863967Z | Cached | 20d35070c8a9a767086d350608cda24a292bad7fbcc1c69e486e2c6125928084 |
| 4.11.0 | 2026-09-08T12:08:49.769141Z | Cached | bdbc622b5406f2773752d3ccdfa686567cbc914a99468760290c9e27817fbddd |
| 4.11.1 | 2026-09-08T14:01:57.316025Z | Cached | 8fdd544f275dcbbdad3012fc497a15dd0a6984fc431130b16ac4929e19e542a8 |
| 4.12.0 | 2026-09-09T10:05:26.803084Z | Cached | 9165bb982487e899e4b35729e821e4e2d2407fb9b0c8d4e07d3ea39e148200ba |
| 4.13.0 | 2026-09-26T17:58:05.220437Z | Cached | 139121951111a41fbd87a422e2915baf4dda8f7f91b3d2c2be2ee18f1bc2c17e |
| 4.13.1 | 2026-09-28T11:33:02.069894Z | Cached | 8bc77b763c571dc3736cf00f011619315d06b917ae986a0a8191813e70c014b2 |
Dependencies
cached_network_image_platform_interface_ce "^5.2.0"
cached_network_image_web_ce "^2.1.0"
clock "^1.1.1"
crypto "^3.0.0"
file "\u003e=7.0.0 \u003c8.0.0"
flutter {
"sdk": "flutter"
}
hive_ce "^2.0.0"
http "^1.6.0"
meta "^1.9.0"
octo_image "^2.1.0"
path "^1.8.0"
path_provider "^2.0.0"