all_image_cache 0.0.9
all_image_cache: ^0.0.9 copied to clipboard
Flutter image cache with memory/disk layers, network/file/bytes sources, SVG support, optional compression, stale fallback, and production-ready widgets.
import 'dart:convert';
import 'dart:typed_data';
import 'package:all_image_cache/all_image_cache.dart';
import 'package:all_observer/all_observer.dart';
import 'package:flutter/material.dart';
import 'controllers/cache_example_controller.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';
late CacheExampleController _controller;
ImageCacheManager get _manager => widget.manager ?? AllImageCache.instance;
@override
void initState() {
super.initState();
_controller = CacheExampleController(
manager: _manager,
directLoadBytes: _samplePng,
);
}
@override
void didUpdateWidget(covariant ExampleHomePage oldWidget) {
super.didUpdateWidget(oldWidget);
if (identical(oldWidget.manager, widget.manager)) return;
_controller.dispose();
_controller = CacheExampleController(
manager: _manager,
directLoadBytes: _samplePng,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@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(
NetworkImageSource(_networkUrl),
manager: _manager,
),
fit: BoxFit.cover,
),
),
),
),
_ExampleSection(
title: 'Direct manager API',
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Observer(
() => Text(
_controller.status.value,
key: const ValueKey('cache-status'),
),
),
const SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 12,
children: [
FilledButton(
key: const ValueKey('direct-load-button'),
onPressed: _controller.loadDirectly,
child: const Text('Direct load'),
),
OutlinedButton(
key: const ValueKey('clear-cache-button'),
onPressed: _controller.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>',
),
);