all_image_cache 0.0.5
all_image_cache: ^0.0.5 copied to clipboard
Flutter image cache with memory/disk layers, network/file/bytes sources, SVG support, optional compression, stale fallback, and production-ready widgets.
example/lib/main.dart
import 'dart:convert';
import 'dart:typed_data';
import 'package:all_image_cache/all_image_cache.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await AllImageCache.init(
containerName: 'all_image_cache_example',
maxEntries: 50,
maxSizeBytes: 20 * 1024 * 1024,
logger: const DebugCacheLogger(),
);
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key, this.manager});
final ImageCacheManager? manager;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'all_image_cache example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: ExampleHomePage(manager: manager),
);
}
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({super.key, this.manager});
final ImageCacheManager? manager;
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
static const _networkUrl =
'https://picsum.photos/seed/all_image_cache/640/360';
String _status = 'Tap direct load to read bytes through the cache manager.';
ImageCacheManager get _manager => widget.manager ?? AllImageCache.instance;
Future<void> _loadDirectly() async {
final bytes = await _manager.getBytes(
BytesImageSource(_samplePng, uniqueKey: 'example://direct-load'),
);
final stats = await _manager.stats();
if (!mounted) return;
setState(() {
_status =
'Loaded ${bytes.length} bytes. Disk cache: ${stats.entryCount} entries, ${stats.totalSizeBytes} bytes.';
});
}
Future<void> _clearCache() async {
await _manager.clear();
final stats = await _manager.stats();
if (!mounted) return;
setState(() {
_status =
'Cache cleared. Disk cache: ${stats.entryCount} entries, ${stats.totalSizeBytes} bytes.';
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('all_image_cache')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_ExampleSection(
title: 'CachedImage.memory',
child: Center(
child: CachedImage.memory(
_samplePng,
uniqueKey: 'example://memory-image',
manager: _manager,
width: 96,
height: 96,
fit: BoxFit.contain,
placeholderBuilder: (_) => const _ImagePlaceholder(),
errorBuilder: (_, error) => _ImageError(error: error),
),
),
),
_ExampleSection(
title: 'CachedImage.network',
child: AspectRatio(
aspectRatio: 16 / 9,
child: CachedImage.network(
_networkUrl,
manager: _manager,
fit: BoxFit.cover,
placeholderBuilder: (_) => const _ImagePlaceholder(),
errorBuilder: (_, error) => _ImageError(error: error),
),
),
),
_ExampleSection(
title: 'CachedSvgImage.memory',
child: Center(
child: CachedSvgImage.memory(
_sampleSvg,
uniqueKey: 'example://memory-svg',
manager: _manager,
width: 96,
height: 96,
placeholderBuilder: (_) => const _ImagePlaceholder(),
errorBuilder: (_, error) => _ImageError(error: error),
),
),
),
_ExampleSection(
title: 'CachedImageProvider',
child: Container(
height: 160,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
image: DecorationImage(
image: CachedImageProvider(
const NetworkImageSource(_networkUrl),
manager: _manager,
),
fit: BoxFit.cover,
),
),
),
),
_ExampleSection(
title: 'Direct manager API',
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(_status),
const SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 12,
children: [
FilledButton(
key: const ValueKey('direct-load-button'),
onPressed: _loadDirectly,
child: const Text('Direct load'),
),
OutlinedButton(
key: const ValueKey('clear-cache-button'),
onPressed: _clearCache,
child: const Text('Clear cache'),
),
],
),
],
),
),
],
),
);
}
}
class _ExampleSection extends StatelessWidget {
const _ExampleSection({required this.title, required this.child});
final String title;
final Widget child;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
child,
],
),
);
}
}
class _ImagePlaceholder extends StatelessWidget {
const _ImagePlaceholder();
@override
Widget build(BuildContext context) {
return const ColoredBox(
color: Color(0xFFE6E8EB),
child: Center(child: CircularProgressIndicator()),
);
}
}
class _ImageError extends StatelessWidget {
const _ImageError({required this.error});
final Object error;
@override
Widget build(BuildContext context) {
return ColoredBox(
color: const Color(0xFFFFE4E6),
child: Center(
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
'Failed to load image: $error',
textAlign: TextAlign.center,
),
),
),
);
}
}
class DebugCacheLogger implements ImageCacheLogger {
const DebugCacheLogger();
@override
void log(CacheEvent event) {
debugPrint(event.toString());
}
}
final Uint8List _samplePng = base64Decode(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAA'
'AAYAAjCB0C8AAAAASUVORK5CYII=',
);
final Uint8List _sampleSvg = Uint8List.fromList(
utf8.encode(
'<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96">'
'<rect width="96" height="96" rx="16" fill="#009688"/>'
'<circle cx="48" cy="48" r="24" fill="#ffffff"/>'
'</svg>',
),
);