※Claude Codeを使用して記事を作成しています。
シリーズ:Claude Codeを使ったAndroidアプリ開発 失敗談
- #10:Composeの再描画が止まらなくなった話(状態管理の誤り) ← 今回
はじめに
Jetpack ComposeはAndroid UIの現代的な書き方ですが、状態管理を誤ると無限に再描画が発生します。
Claude Codeが生成したコードでも、この問題は起きることがあります。
やらかしたこと
メモ一覧画面をスクロールすると、目に見えてカクつくようになりました。
Android Profilerで確認すると、コンポーザブル関数が毎フレーム再実行されている状態でした。
該当コードを見ると:
// Claude Codeが生成したコード(問題あり)
@Composable
fun MemoListScreen(viewModel: MemoListViewModel = hiltViewModel()) {
val memos by viewModel.memos.collectAsState()
LazyColumn {
items(memos, key = { UUID.randomUUID().toString() }) { memo -> // ← 問題
MemoItem(memo = memo)
}
}
}
key = { UUID.randomUUID().toString() } の部分が問題でした。
再描画のたびに新しいUUIDが生成されるため、Composeがすべてのアイテムを「新しいもの」と判断して毎回再描画していました。
どう直したか
メモ一覧でLazyColumnを使っていますが、
再描画が毎フレーム発生してパフォーマンスが悪い状態です。
keyに UUID.randomUUID() を使っているのが原因と思われます。
メモのIDを安定したkeyとして使うように修正してください。
また、他に不必要な再描画を引き起こしている箇所があれば
合わせて修正してください。
修正後:
items(memos, key = { memo -> memo.id }) { memo -> // 安定したkey
MemoItem(memo = memo)
}
ComposeをClaude Codeで使う際の注意点
Composeの状態管理で特に気をつけるポイントを、確認用の指示としてまとめました。
実装したコンポーザブルに以下の問題がないか確認してください。
・LazyColumnのkeyに不安定な値(random等)を使っていないか
・rememberを使わずにオブジェクトをコンポーザブル内で生成していないか
・Stateを引数で渡すのではなく直接collectしていないか
・不必要にrecomposeが走るコードになっていないか
問題があれば修正してください。
まとめ
Composeは宣言的UIで直感的に書けますが、パフォーマンスの落とし穴が細かい場所に潜んでいます。Claude Codeに「パフォーマンスの観点でも確認して」と一言添えることで、このような問題を未然に防げます。
次回:【Claude Code 失敗談 #11】Claude Codeに任せすぎてコードの意味が全くわからなくなった話

