Appearance
源码:labs/flutter/host/lib/topics/image_loading/cached_network_image_demo_page.dart
- 原始路径:
labs/flutter/host/lib/topics/image_loading/cached_network_image_demo_page.dart - 类型:
dart
dart
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
/// Flutter 图片加载演示:对应 docs/11-image-loading/04-flutter-image-loading.md
///
/// 覆盖:
/// - CachedNetworkImage 网络图 + 占位 / 进度 / 失败回调
/// - memCacheWidth 解码降采样(等价于 Android inBitmap / inSampleSize)
/// - 缓存清理:ImageCache(内存)与 CachedNetworkImage(磁盘)两层
class CachedNetworkImageDemoPage extends StatefulWidget {
const CachedNetworkImageDemoPage({super.key});
static const routeName = '/image_loading';
@override
State<CachedNetworkImageDemoPage> createState() =>
_CachedNetworkImageDemoPageState();
}
class _CachedNetworkImageDemoPageState
extends State<CachedNetworkImageDemoPage> {
static const _url =
'https://picsum.photos/seed/flutter_image_lab/800/600';
String _status = '等待操作';
void _clearMemoryCache() {
imageCache.clear();
imageCache.clearLiveImages();
setState(() => _status = '已清空 ImageCache(内存)');
}
Future<void> _clearDiskCache() async {
await CachedNetworkImage.evictFromCache(_url);
// async gap 后先检查 mounted,避免页面已销毁时调用 setState 报错
if (!mounted) return;
setState(() => _status = '已驱逐磁盘缓存(下次需重新下载)');
}
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
appBar: AppBar(title: const Text('Flutter 图片加载')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
const Text(
'CachedNetworkImage:网络图 + 占位 / 进度 / 失败 + 磁盘缓存',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: CachedNetworkImage(
imageUrl: _url,
fit: BoxFit.cover,
placeholder: (context, url) => const SizedBox(
height: 200,
child: Center(child: CircularProgressIndicator()),
),
errorWidget: (context, url, error) =>
const Icon(Icons.error, size: 48),
fadeInDuration: const Duration(milliseconds: 300),
memCacheWidth: 800,
),
),
const SizedBox(height: 16),
const Text(
'解码降采样(memCacheWidth = 200):内存随面积下降',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: CachedNetworkImage(
imageUrl: _url,
memCacheWidth: 200,
fit: BoxFit.cover,
placeholder: (context, url) => const SizedBox(
height: 120,
child: Center(child: CircularProgressIndicator()),
),
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
const SizedBox(height: 16),
Text(
'状态:$_status',
style: TextStyle(color: colorScheme.onSurfaceVariant),
),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
FilledButton.icon(
onPressed: _clearMemoryCache,
icon: const Icon(Icons.memory),
label: const Text('清内存缓存 (ImageCache)'),
),
OutlinedButton.icon(
onPressed: _clearDiskCache,
icon: const Icon(Icons.storage),
label: const Text('清磁盘缓存 (CachedNetworkImage)'),
),
],
),
const SizedBox(height: 12),
const Text(
'要点:ImageCache 是 Dart 侧内存 LRU(数量 + 字节双限);'
'CachedNetworkImage 额外提供设备磁盘缓存。两者是两层,'
'清内存不代表清磁盘。超大图务必设 memCacheWidth / cacheWidth 降采样。',
style: TextStyle(fontSize: 13),
),
],
),
);
}
}