🐷

はやい・うまい・JetpackCompose

2022/06/15に公開

Engineer LT#1 Android|Organized by U-NEXTにて発表した内容を記事化しました。

お品書き

発表内容はこちらになります。
Google I/Oの動画や公式ブログに書かれていることもあり、
前半は軽く流します。

Releaseビルドする


Composeを使用していてパフォーマンスに問題が出た時には、
minifyをenabledしてR8コンパイラを有効にしてreleaseビルドをして動作確認してください
ただ、実装中などにパフォーマンス問題があるのもツラいのでデバッグでも早くなって欲しいです。

Composable関数内に計算処理を書かない



こちらのサンプルのようにソート処理などの計算処理をComposable関数内に書くと再Composeされた時に毎回計算(ソート)処理が走るのでパフォーマンスに問題が出る可能性があります。


毎回計算処理が走ることを防ぐためにrememberを使用してください


より良い方法としてViewModelなどで計算処理は終わらせておき、
その結果をComposableに渡すようにすると良いです。

Lazy Layoutsではkeyを指定する



例えばこのような処理があったとします。
特に問題なく動作するコードですが・・・


表示されているアイテムのNote5の内容が更新され、更新された事をきっかけにindex0に移動すると、
item1〜item5の全てが再Composeされてしまいます。


このようにkeyを指定するように修正すると・・・

Note5は内容の更新があるので再Composeされます。
が、Note1〜4は今までindex0〜3にいたアイテムだと自身で判断しキャッシュを使用することが可能になりパフォーマンスが向上します。

特定の条件でのみStateを変更する



このようなスクロール中常に情報更新される処理があるとします。
このコードだとユーザがスクロールしている間中常にAnimatedVisibilityにStateの更新が通知されます。


そこでderivedStateOfを使うと、実際に変更の通知が必要なtrue/falseが変わるタイミングでのみStateの変更が通知されるようになります。

ラムダ関数を渡そう



こちら再びスクロールの情報を渡すコードになります。
このように一番上のComposableであるBox内でStateを読んでしまうと、
左の赤線が引かれている部分(Boxとその中身)が再Composeされてしまいます。


そこで、このようにBoxではTitleに対してラムダ関数を渡すようにすると、
BoxではStateを読まないので再Composeがされなくなります。


さらに本当にStateを必要とする最深部で読み込むようにするとさらに効率が上がります。

drawBihindを使おう



このサンプルのanimatedColorBetweenは引数で指定した色を交互に切り替える処理になります。
そこで受け取った色をBoxの背景に指定しています。
このままでも特に問題は無いのですが・・・


drawBihindを使用すると描画フェーズでのみStateを読むようになります。
描画フェーズでのみStateを読まれるようになると何がいいのかと言うと・・・


JetpackCpomposeはこちら3個の工程を実行して画面の描画をしています。
そして、その工程は変更の必要が無い時にはキャッシュを使用してスキップされます。
今回のように描画フェーズのみ変更するようにすることで、CompositionとLayoutの工程をスキップできるのでパフォーマンスが改善します。

読み込まれたStateに書き込まない



このコードの様に読み込んだCountに処理の最後でインクリメントするような処理があった場合、
再Composeが無限ループで実行されてしまうので、Stateの書き込みは注意が必要です。

RecyclerView内のComposable



今までパフォーマンスが悪いと有名だったRecyclerView内のComposableですが、
RecyclerView 1.3.0-alpha02とCompose 1.2.0-alpha06以上を組み合わせると
パフォーマンスが改善されたようです。

手軽にデバッグ



Compose1.2.0-alpha03以上とAndroid Studio Electric Eelが使える環境の場合はLayout Inspectorで再Composeの回数が確認できます。
数字だけでなく赤く色がついて視覚的にも分かりやすい機能となっています。


そんなに新しいバージョンを入れられない環境の方はこちらの
recomposeHighlighterを使用してください
※物はこちらですhttps://github.com/android/snippets/blob/master/compose/recomposehighlighter/src/main/java/com/example/android/compose/recomposehighlighter/RecomposeHighlighter.kt


こちらを使用すると再Composeされた回数に応じて枠線が引かれ視覚的に再Composeの状況が分かるようになります。

ComposeCompilerMetricsを使う



ここまでは視覚に頼るデバッグ方法を紹介しましたが、ComposeCompilerMetricsを使用すると、
コンパイラがどのような解析をしているのかがログとして出力されるので、
こちらの方が使いやすいタイミングもあるかと思います。
が、参考URLに記載されているようにComposeのバージョンによって上手く導入できない事もあるので、
導入が難しい場合には視覚に頼った方法を使うことになります。

https://blog.mokelab.com/77/Compose_Report.html

参考情報



参考情報はこちらです。
※URLへのリンクは最後に書きます。

最後に



最後に、端末によって本当にパフォーマンス問題が出たりするので、なるべく多くの端末で動作確認することをオススメします。
古すぎる訳でもないPixel3aでのみパフォーマンスが落ちることがあったりして泣いたりしています。

参考リンク集

Compose performance
https://developer.android.com/jetpack/compose/performance

How can I debug recompositions in Jetpack Compose?
https://www.jetpackcompose.app/articles/how-can-I-debug-recompositions-in-jetpack-compose

Performance best practices for Jetpack Compose
https://youtu.be/EOQB8PTLkpY

android/snippets
https://github.com/android/snippets/blob/master/compose/recomposehighlighter/src/main/java/com/example/android/compose/recomposehighlighter/RecomposeHighlighter.kt

#77 Jetpack Composeのコンパイラプラグインのレポートを生成する
https://blog.mokelab.com/77/Compose_Report.html

Jetpack Compose Phases
https://developer.android.com/jetpack/compose/phases

Discussion