◉ANTIGRAVITY LABEN
記事一覧/アプリ開発
▣ アプリ開発/2026-06-25上級

お気に入りを一つ押すたびに、見えている壁紙が全部描き直されていた — Compose の再コンポーズを実測で止めた記録

壁紙アプリのグリッドで、お気に入りを一つ切り替えるたびに可視サムネイル全件が再コンポーズされていた問題を、Composition Tracing で実測してから直した記録です。不安定な引数の特定、データモデルの安定化、ラムダと派生状態の扱い、修正前後の再コンポーズ回数の比較までを個人開発の視点でまとめました。

Android27Jetpack Compose6再コンポーズパフォーマンス最適化3Composition Tracing

✦ プレミアム記事

壁紙アプリのお気に入り一覧を作り直していたとき、サムネイルのハートを一つ押すたびに、画面に見えている十数枚のサムネイルがほんの一瞬ちらつくのに気づきました。タップした一枚だけが切り替わってほしいのに、可視範囲のセル全部が描き直されているような挙動です。

スクロール中だと、このちらつきがそのままカクつきになります。自分の Pixel では辛うじて滑らかでも、古い端末を貸してくれる知人の手元では明らかに引っかかる。個人開発で同じアプリを長く触っていると、自分の端末の速さに慣れてしまって、こういう劣化を見落とします。気づいたのは、低速端末でスクロールしながらお気に入りを連打したときでした。原因は Jetpack Compose の再コンポーズ範囲が広がりっぱなしになっていたことで、まず「何回描き直されているか」を数字にするところから手をつけました。

推測でチューニングを始めない — まず再コンポーズ回数を可視化する

Compose のパフォーマンス問題でいちばんやってはいけないのは、remember や key を勘で足していくことです。どの Composable が何回再コンポーズされているか分からないまま手を入れると、効いたのか効いていないのか判断できず、別の場所を壊します。

最初にやったのは Composition Tracing の有効化でした。System Trace に「どの Composable 関数が何回コンポーズ/再コンポーズされたか」が名前付きで載るようになります。このセットアップ自体は定型作業なので、Antigravity のエージェントに「composition tracing を有効化して、デバッグビルドでだけ計測できるようにして」と頼み、出てきた差分を私が確認しました。

// app/build.gradle.kts
dependencies {
    // Composition Tracing 用(debug のみで十分)
    implementation("androidx.tracing:tracing-perfetto:1.0.0")
    implementation("androidx.tracing:tracing-perfetto-binary:1.0.0")
}
 
// Compose コンパイラに composition tracing マーカーを埋め込ませる
composeCompiler {
    // デバッグ計測時のみ true。リリースには含めない
    includeTraceMarkers = true
}

計測は Android Studio の System Trace プロファイラ、もしくは Macrobenchmark から androidx.tracing.perfetto を起動して取りました。起動後にお気に入りを一回トグルし、トレースを Perfetto で開いて、サムネイル Composable のスライス数を数えます。ここで「一回のトグルで可視セル数ぶんの再コンポーズが走っている」ことが、初めて疑いではなく事実になりました。

犯人は「不安定な引数」だった

再コンポーズが広がる典型は、Composable に渡している引数が Compose コンパイラから「不安定(unstable)」と判定されているケースです。不安定な引数を一つでも受け取る Composable は、スキップ(skippable)の対象から外れ、親が再コンポーズされるたびに無条件で再コンポーズされます。

私のグリッドのアイテムは、こんなデータクラスを受け取っていました。

// 一見ふつうのモデル。だが Compose からは unstable に見える
data class WallpaperItem(
    val id: String,
    val thumbnailUrl: String,
    val tags: List<String>,        // ← List はインターフェースなので unstable 扱い
    var isFavorite: Boolean,       // ← var は unstable の決定打
)

List<String> は実装が差し替わりうるインターフェース型なので、コンパイラは中身が変わらない保証がないと判断します。さらに var プロパティは、いつ書き換わるか分からないため不安定の決定打です。この一つのモデルが unstable なせいで、それを受け取るサムネイル Composable 全体が skippable でなくなり、お気に入りの Set が更新されて親が再コンポーズされるたびに、可視セルが全部巻き込まれていました。

安定性の判定は、Compose コンパイラのレポート出力で確認できます。

# build.gradle.kts に compiler reports を出す設定を入れた上で
./gradlew assembleRelease \
  -Pandroidx.compose.compiler.reports.destination=build/compose_reports
 
# 生成された *-classes.txt を見ると stable/unstable が一覧で出る
# 例: unstable class WallpaperItem
✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦Composition Tracing を仕込み、どの Composable が一操作で何回再コンポーズされているかを推測ではなく数値として読めるようになります
✦LazyVerticalGrid が favorite トグルのたびに可視サムネイル全件を描き直していた原因を不安定な引数まで特定し、@Immutable・安定キー・derivedStateOf で再コンポーズを必要な一件に絞り込めるようになります
✦修正前後の再コンポーズ回数とスクロール時のフレーム時間を Before/After で比較し、個人開発でどこまでエージェントに計測を任せどの判断を自分で握るかの線引きを持てるようになります
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

▣ アプリ開発2026-05-25
Antigravity の Inline Edit と Agent モードを壁紙アプリ運用で1ヶ月使い分けた所感
壁紙アプリ4本の実運用で Antigravity の Inline Edit と Agent モードを1ヶ月使い分けた所感です。実測値・AGENTS.md への判断軸の固定・dSYM 一括統一・クレジット消費まで、現実的な運用設計を共有します。
▣ アプリ開発2026-10-08
agy CLI をコンテナで動かす前に、擬似 agy で確かめておく 3 つの安全網
Antigravity CLI(agy)を Docker や Cloud Run のジョブから呼ぶ前に、インストーラーの取りこぼし・承認待ちの固まり・終了コード 0 の空振りを、擬似 agy で再現して潰します。公式 docs の記述と、手元で実行した結果だけを根拠に組み立てた手順です。
▣ アプリ開発2026-09-29
Cloudflare をパージしても古い壁紙が届き続けた原因は、オリジン側で JPEG を握っていた XPageSpeed
同じ URL に上書きした壁紙画像が、Cloudflare をパージしても古いまま届き続けた運用の記録です。ローカル・オリジン・エッジの三者を突き合わせて層を名指しする検査、プレフィックスパージの使いどころ、Xserver の XPageSpeed を .htaccess で安全に切る書き方まで扱います。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます