開発

Flutterで画像をキャッシュする方法:
cached_network_imageとFadeInImage完全ガイド

· SEADICE

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_imageFadeInImageImage.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を推奨します。

← ブログ一覧に戻る