公開日: 2024/02/29
ComposeのStabilityはComposableのRecomposeによるパフォーマンス低下を改善するための重要な概念の一つです。
しかしながら少し複雑で理解しにくい部分があるため本記事でStabilityについてわかりやすく解説します。
結論から説明するとStabilityとは「不要なRecompositionをスキップして効率的にUIを更新するための概念」のことです。
この意味が少しわかりづらいと思うので順を追って説明していきます。
RecompositionとはComposable関数のパラメータが変更されたときに、Composable関数を再実行することです。
例えば、以下のようなComposable関数があるとします。
(Android Developersの説明わかりやすいので引用して説明します)
@Composable
fun LoginScreen(showError: Boolean) {
if (showError) {
LoginError()
}
LoginInput()
}
@Composable
fun LoginInput() { /* ... */ }
@Composable
fun LoginError() { /* ... */ }
Composable関数LoginScreenのshowErrorパラメータが変更されるとRecompositionが発生し、下図のようにCompositionツリーが更新されます。

Recompositionが発生してCompositionツリーが更新されている様子
また効率的にUIを更新するために、以下2つの条件を満たしたComposable関数はRecompositionをスキップすることができます。
stableである条件の詳細を順番に解説します。
これは全てのパラメータをObject.equals()で比較することで判断をします。
例えば、initialUiStateとupdatedUiStateはメモリの参照先は違いますが同じtextの文字列hogeを持っているので、Object.equals()はtrueとなります。
data class UiState(
val text: String
)
val initialUiState = UiState(
text = "hoge"
)
val updatedUiState = UiState(
text = "hoge"
)
initialUiState.equals(updatedUiState) // => true
initialUiState === updatedUiState // => false
stableであるここで登場するのがStabilityの概念です。
Composable関数のパラメータはstableかunstableに分類されます。
下記の2つのどちらかを満たすパラメータをstableと言います。(満たさないパラメータをunstableと言います)
型がimmutableであるとは、インスタンス生成したあと公開されているプロパティの値を変更できないことを表します。つまりインスタンスのプロパティを変更したい場合は新しくインスタンスを作り直す必要があります。
Boolean,Float,Intなどのプリミティブ型やStringについてもimmutableな型となります。
以下のクラスもimmutableとなります。
data class Post(
val id: Int,
val title: String,
val description: String,
)
すべてのプロパティはvalで定義されたプリミティブ型であり、Postのプロパティの値を変更するには新しくインスタンスを作り直す必要があるからです。
以下のクラスはimmutableではありません。
data class Title(
var text: String
)
Titleクラスのプロパティtextがvarで定義されており、プロパティの値を変更が可能であるためです。
以下のようにMutableState、SnapshotStateMap、SnapshotStateListなどを使用したプロパティであればComposeランタイが値の変更を知ることができます。
例えばtextの型はMutableState<String>となり、text.value = "hoge"のように記述することで値を変更できます。しかしながらこの値の変更をComposeランタイムに通知されるようになります。
data class Hoge(
val text by mutableStateOf("")
)
前述の通り、StabilityとはRecompositionと深いつながりがあり、不要なRecompositionをスキップして効率的にUIを更新するために用いられることがわかったかと思います。
参考になれば幸いです。
https://developer.android.com/jetpack/compose/performance/stability