📷
[Jetpack Compose] snapshotFlow の解説
はじめに
自分が調べたもののまとめです。
snapshotFlow の簡単なまとめ
- State の変更を監視するのに使う。
- State<T> の特定の属性の変更のみを監視する使い方もできる(その使い方がメイン?)
- 内部的に Snapshot が利用されている
サンプル1
簡単な使い方の例
snapshotFlow の引数の block で参照している State (例での counter)が監視対象になる。
import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
@Composable
fun SnapshotFlowSample() {
var counter = remember { mutableStateOf(0) }
LaunchedEffect(counter) {
snapshotFlow { counter }
.collect { // it: MutableState<Int>
Log.d("App", "collected ${it.value}")
}
}
Column() {
Button(
onClick = { counter.value = counter.value + 1 }
) {
Text("countUp")
}
}
}
サンプル2
ブロックで返却する値は T の属性でもよい。その場合、返却値に変更があった場合のみ emit される。
import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
@Composable
fun SnapshotFlowSample() {
val pairCounter = remember { mutableStateOf(Pair(0, 0)) }
LaunchedEffect(pairCounter) {
// 第一項( first ) のみ監視する
snapshotFlow { pairCounter.value.first }
.collect {// it: Int
Log.d("App", "collected $it")
}
}
Column {
Button(
onClick = { pairCounter.value = pairCounter.value.copy(first = pairCounter.value.first + 1)}
) {
Text("countUp first")
}
Button(
onClick = { pairCounter.value = pairCounter.value.copy(second = pairCounter.value.second + 1)}
) {
Text("countUp second")
}
}
}
実行結果
collected 0
collected 1
collected 2
// second の変更は emit されない
よくある使い方
LazyListState.firstVisibleItemIndex を snapshotFlow で監視し、リストの要素のどこまでが表示されたかを分析・トラッキングするのに利用するのが一般的というか、典型的な例。
(おまけ) Snapshot
ある時点での全ての状態のスナップショットをとるもの
-
snapshot に対して、その snapshot からの状態の変更を監視する仕組みがある( Snapshot.registerApplyObserver など)。
-
snapshotFlow では
- 全ての状態の変更を監視し
- snapshotFlow で参照した状態の変更が発生した場合
- block を再評価して返却値が変化した場合に emit
ということが行われている(っぽい)
-
-
Snapshot は jetpack compose の基礎部分である状態の変更を検知して recomposition が行われる仕組みに利用されている(っぽい)。
Discussion