Flutterで画像をキャッシュする方法:
cached_network_imageとFadeInImage完全ガイド
Flutterでネットワーク画像をキャッシュするにはcached_network_imageパッケージが最速の解決策だ。pubspec.yamlに1行追加するだけで、自動ディスクキャッシュ・ローディング表示・エラー表示をまとめて実装できる。
なぜ画像キャッシュが必要か
標準のImage.networkはキャッシュを持たず、画面を再描画するたびにネットワークから画像を再取得する。リスト表示で100枚の画像があれば100回のHTTPリクエストが発生し、UXとパフォーマンスの両方に悪影響が出る。
- スクロール時にちらつき・ローディングが繰り返し発生する
- オフライン時に画像が一切表示されない
- 通信量が増えてユーザーのデータプランを消費する
- サーバーへのリクエスト数が増えてコストが上がる
cached_network_imageの導入方法
cached_network_image ^3.3.0を追加するだけで、ディスクキャッシュ・メモリキャッシュが自動的に有効になる。
1. pubspec.yamlに追加
dependencies:
cached_network_image: ^3.3.0
2. 基本的な使い方
import 'package:cached_network_image/cached_network_image.dart';
CachedNetworkImage(
imageUrl: 'https://example.com/image.jpg',
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.broken_image),
fit: BoxFit.cover,
width: 200,
height: 200,
)
3. リスト表示での使い方(パフォーマンス最適化)
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) => CachedNetworkImage(
imageUrl: items[index].imageUrl,
memCacheWidth: 400, // メモリキャッシュのリサイズ幅
memCacheHeight: 400, // 表示サイズに合わせて設定
placeholder: (_, __) => Container(
color: const Color(0xFF0C0C1A),
child: const Center(child: CircularProgressIndicator()),
),
errorWidget: (_, __, ___) => Container(
color: const Color(0xFF0C0C1A),
child: const Icon(Icons.image_not_supported, color: Colors.white24),
),
fit: BoxFit.cover,
),
)
memCacheWidth/memCacheHeightを表示サイズに合わせて設定するとメモリ使用量を大幅に削減できる。1000×1000の画像を100×100で表示する場合、100倍のメモリ差が生まれる。
FadeInImage:標準機能でのキャッシュ
パッケージを使わずに済む場合はFadeInImageが使える。ただしディスクキャッシュはアプリ起動中のみ有効で、再起動後はキャッシュが失われる点がcached_network_imageとの大きな違いだ。
FadeInImage.assetNetwork(
placeholder: 'assets/images/placeholder.png',
image: 'https://example.com/image.jpg',
fit: BoxFit.cover,
fadeInDuration: const Duration(milliseconds: 300),
)
| 比較項目 | cached_network_image | FadeInImage | Image.network |
|---|---|---|---|
| ディスクキャッシュ | あり(30日) | なし | なし |
| メモリキャッシュ | あり | あり | あり |
| オフライン表示 | 可能 | 不可 | 不可 |
| パッケージ依存 | 必要 | 不要 | 不要 |
| エラーウィジェット | 簡単 | 手動実装 | 手動実装 |
キャッシュの管理・クリア方法
キャッシュが古くなった場合や容量を節約したい場合は、プログラムからキャッシュを操作できる。
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
// 特定URLのキャッシュを削除
await CachedNetworkImage.evictFromCache(imageUrl);
// 全キャッシュを削除
await DefaultCacheManager().emptyCache();
// キャッシュの有効期限を変更(デフォルト30日)
final customCacheManager = CacheManager(
Config(
'customCache',
stalePeriod: const Duration(days: 7),
maxNrOfCacheObjects: 100,
),
);
CachedNetworkImage(
imageUrl: url,
cacheManager: customCacheManager,
)
よくある質問
cached_network_imageとImage.networkの違いは何ですか?
Image.networkはキャッシュを持たず毎回ネットワークから画像を取得します。cached_network_imageはディスクキャッシュを自動管理し、一度取得した画像は次回以降ネットワークなしで表示できます。
Flutterのキャッシュはどこに保存されますか?
cached_network_imageはアプリのキャッシュディレクトリ(iOS: Library/Caches)にファイルとして保存されます。デフォルトのキャッシュ有効期限は30日です。
キャッシュをクリアする方法は?
CachedNetworkImage.evictFromCache(url)で特定URLのキャッシュを削除できます。全キャッシュを削除するにはDefaultCacheManager().emptyCache()を呼びます。
WebPとPNGどちらが速いですか?
WebPはPNGと比較して約25〜35%ファイルサイズが小さくなります。ネットワーク転送が速くなるため、特にリスト表示など多数の画像を扱う場面ではWebPを推奨します。