Compose までの Flow の collect
coroutine など非同期処理を行う場合ライフサイクルの考慮が必要でしたね!
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.lifecycle.repeatOnLifecycle(STARTED) {
myViewModel.myUiState.collect {
// ...
}
}
}
これは、Fragment のビューが STARTED になったときに収集を開始し、RESUMED まで継続し、STOPPED に戻ったときに停止します。
👉 【MVVM】 Kotlin Flow で使える5つの利用パターン
生き死にだけでではないのです。
collect する期間も考えなくてはなりません。
Compose では
@Composable 内で、
val items by viewModel.items.collectAsState(initial = emptyList())
というような形で、かんたんに Flow や StateFlow を 収集できます。
しかし、
バックスタック中に、無駄に APIにリクエストしたり、DBにクエリーを投げたりしてません?
逆に、更新されずに古いままの更新されてない画面見せられたりして萎えたりもします。
collectAsStateWithLifecycle() の登場
👉 collectAsStateWithLifecycleが追加されたぞ - Qiita
所属は以下のようです。
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0-alpha01"
実装を見てみます。
ホットな StateFlow と コールドな Flow に向けて2つずつ公開されています。
fun <T> StateFlow<T>.collectAsStateWithLifecycle(
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
context: CoroutineContext = EmptyCoroutineContext
): State<T>
fun <T> StateFlow<T>.collectAsStateWithLifecycle(
lifecycle: Lifecycle,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
context: CoroutineContext = EmptyCoroutineContext
): State<T>
fun <T> Flow<T>.collectAsStateWithLifecycle(
initialValue: T,
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
context: CoroutineContext = EmptyCoroutineContext
): State<T>
fun <T> Flow<T>.collectAsStateWithLifecycle(
initialValue: T,
lifecycle: Lifecycle,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
context: CoroutineContext = EmptyCoroutineContext
): State<T>
ライフサイクルや期間を与えて collect 動作を設定できます。
ありがとうございます。
LifecycleOwner は誰なのか
前述引用の実装コードより。
...
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
...
LocalLifecycleOwner
ライフサイクルのオーナーといえば、Compose 以前は、
Activity、Fragment、View
ぐらいで考えていましたが。
きっとオーナーは、Activity ではなく、
最上位のルートの @Composable
ではなかろうか。
いや、ワンチャン Activity かもしれん。
見てみましょう。
println("オーナー → ${LocalLifecycleOwner.current}")
結果
D: オーナー → androidx.navigation.NavBackStackEntry@4dc222c4
「NavBackStackEntry」さんらしいですわ。