画像のパフォーマンスの最適化

画像を扱う場合は、注意しないとパフォーマンスの問題が起こりやすくなります。大きなビットマップを扱う場合は、OutOfMemoryError がすぐに発生する可能性があります。アプリのパフォーマンスを最大限に高めるには、以下のおすすめの方法を実施してください。

必要なサイズのビットマップのみを読み込む

ほとんどのスマートフォンには、大きい画像ファイルを生成する高解像度カメラが搭載されています。画像を画面に表示する場合は、画像の解像度を下げるか、画像コンテナのサイズの範囲内で画像を読み込む必要があります。必要以上に大きい画像を常時読み込むと、GPU キャッシュが使い果たされ、UI レンダリングのパフォーマンスの低下につながる可能性があります。

画像サイズを管理するには:

  • 画像ファイルを縮小して(出力画像に影響しない程度に)できるだけ小さくします。
  • JPEG または PNG ではなく、画像を WEBP 形式に変換することを検討します。
  • さまざまな画面解像度向けの小さい画像を用意します(ヒント #3 を参照)。
  • 画面上のビューのサイズに合わせて画像を縮小する画像読み込みライブラリを使用します。これは、画面の読み込みパフォーマンスの向上に役立ちます。

可能な場合はビットマップではなくベクターを使用する

画面上で視覚的に何かを表現する場合は、それをベクターとして表現できるかどうかを判断する必要があります。ビットマップよりベクター画像を優先してください。画像をさまざまなサイズにスケーリングしてもモザイク状にならないからです。ただし、あらゆるものがベクターとして表現できるわけではありません。たとえば、カメラで撮影した画像はベクターに変換できません。

各種の画面サイズ向けに代替リソースを供給する

アプリで画像を提供する場合は、異なるデバイス解像度に合わせて異なるサイズのアセットを供給することを検討してください。これにより、デバイス上のアプリのダウンロード サイズを削減できます。また、低解像度のデバイスでは低解像度の画像が読み込まれるため、パフォーマンスが向上します。各種のデバイスサイズ向けに代替ビットマップを提供する方法の詳細については、代替ビットマップ ドキュメントを確認してください

ImageBitmap を使用する場合は、描画する前に prepareToDraw を呼び出します。

ImageBitmap を使用する場合、GPU にテクスチャをアップロードするプロセスを開始するには、実際に描画する前に ImageBitmap#prepareToDraw() を呼び出します。これは GPU がテクスチャを準備するのに役立ち、画面上に画像を表示するパフォーマンスが向上します。ほとんどの画像読み込みライブラリはこの最適化をすでに行っていますが、ご自身で ImageBitmap クラスを扱う場合はこの点に留意してください。

Painter ではなく、Int DrawableRes または URL をパラメータとしてコンポーザブルに渡すことをおすすめします。

画像の処理は複雑であるため(たとえば Bitmaps の equals 関数を記述すると計算コストが高くなります)、Painter API は明示的には安定したクラスとしてマークされていません。安定していないクラスは、データが変更されたかどうかをコンパイラが容易に推測できないため、不要な再コンポジションを発生させる可能性があります。

したがって、Painter をパラメータとしてコンポーザブルに渡すのではなく、URL またはドローアブル リソース ID をパラメータとして渡すことをおすすめします。

// Prefer this:
@Composable
fun MyImage(url: String) {

}
// Over this:
@Composable
fun MyImage(painter: Painter) {

}

必要以上のビットマップをメモリに保存しない

メモリに読み込むビットマップが多くなると、デバイスのメモリが不足する可能性が高くなります。たとえば、画面上で画像コンポーザブルの大きいリストを読み込む場合は、LazyColumn または LazyRow を使用して、大きいリストをスクロールする際にメモリが解放されるようにします。

大きい画像を AAB / APK ファイルと一緒にパッケージ化しない

アプリのダウンロード サイズが大きくなる主な原因の一つとして、AAB または APK ファイル内にパッケージ化されるグラフィックがあります。APK Analyzer ツールを使用して、必要な画像ファイルよりも大きいパッケージを作成しないようにします。サイズを小さくするか、または画像をサーバーに配置して必要なときだけダウンロードすることを検討してください。