Slide 1

Slide 1 text

©2023 RAKUS Co., Ltd. rememberUpdatedState の使いどころを考える potatotips #85 iOS/Android開発Tips共有会 2023/11/14 @akkiee76

Slide 2

Slide 2 text

自己紹介 ● Akihiko Sato ● Rakus Inc. ● 楽楽精算 ● @akkiee76 / X

Slide 3

Slide 3 text

rememberUpdatedState とは?

Slide 4

Slide 4 text

Compose における Side effect APIs の1つ

Slide 5

Slide 5 text

Compose 可能な関数の範囲外で発生するアプリの状態の変化 ● 予想しない再コンポジション ● 異なる順序でのコンポーザブルの再コンポジション ● 破棄可能な再コンポジション Compose における Side effect(副作用)とは? コンポーザブルは Side effect がないようにするのが理想的 https://developer.android.com/jetpack/compose/side-effects

Slide 6

Slide 6 text

● スナックバーを表示する ● 1 回限りのイベントをトリガーする ● 特定の状態で別の画面に遷移する Side effect が必要なケース https://developer.android.com/jetpack/compose/side-effects 予測可能な方法で Side effect を実行する必要がある

Slide 7

Slide 7 text

rememberUpdatedState API とは? 値が変化しても再起動すべきでない作用を 参照することができる Side effect API https://developer.android.com/jetpack/compose/side-effects?hl=jp#rememberupdatedstate 再起動が高コストである作用にアプローチができる

Slide 8

Slide 8 text

最新の時刻を Snackbar に表示するユースケース 1. remember を利用した場合 2. LaunchedEffect のキーを更新した場合 3. rememberUpdatedState API を利用した場合

Slide 9

Slide 9 text

1. remember を利用した場合

Slide 10

Slide 10 text

var currentTime by remember { mutableStateOf(Date().time.toString()) } Button( onClick = { currentTime = Date().time.toString() } ) { Text(currentTime) } SnackbarScreen ( currentTime = currentTime, snackbarHostState = snackbarHostState ) 時刻を保持 時刻を更新 時刻を渡す

Slide 11

Slide 11 text

@Composable fun SnackbarScreen( currentTime: String, snackbarHostState: SnackbarHostState ) { LaunchedEffect(Unit) { delay(3000) snackbarHostState.showSnackbar(message = currentTime) } } 一度だけ実行

Slide 12

Slide 12 text

2. LaunchedEffect の key を更新した場合

Slide 13

Slide 13 text

@Composable fun SnackbarScreen( currentTime: String, snackbarHostState: SnackbarHostState ) { LaunchedEffect(currentTime) { delay(3000) snackbarHostState.showSnackbar(message = currentTime) } } 何も表示されない LaunchedEffect が再起動し Coroutine がキャンセル currentTimeが更新され続ける

Slide 14

Slide 14 text

3. rememberUpdatedState API を利用した場合

Slide 15

Slide 15 text

@Composable fun SnackbarScreen ( currentTime: String, snackbarHostState : SnackbarHostState ) { val rememberTime by rememberUpdatedState (newValue = currentTime) LaunchedEffect (Unit) { delay(3000) snackbarHostState .showSnackbar( message = rememberTime) } } 最新の値が表示 値が変化しても LaunchedEffect の Coroutine はキャンセルされない currentTimeが更新され続ける

Slide 16

Slide 16 text

@Composable fun rememberUpdatedState(newValue: T): State = remember { mutableStateOf(newValue) }.apply { value = newValue } オブジェクトをキャプチャーし、中身を更新している

Slide 17

Slide 17 text

まとめ rememberUpdatedState API の使いどころ ● Coroutine の処理をキャンセルさせたくないケース ○ 重い通信処理(ファイルダウンロード)など ● コールバックを利用するケース ○ エラーハンドリングなど ● 異なる Composable などで変更される値を参照するケース

Slide 18

Slide 18 text

Thank you 🎉