
Jetpack Composeにおける画面遷移を伴わないLazyColumnのスクロール位置のリセットについて
最近趣味でAndroidアプリ開発を行っているが、Jetpack ComposeのLazyColumnで画面遷移を伴わない場合のスクロール位置のリセットをどのように実装するか迷っている。
例えば、LazyColumnに表示するリストの内容が更新された時、その再コンポーズ時に一度だけスクロール可能な時に位置をリセットしたい(index=0)
普通はrememberLazyListStateでLazyListStateを取得すると思う。だがその場合、画面遷移の最初の1度だけ、LazyListStateのインスタンスが取得される。つまり、リストの内容が更新されようとも、スクロール位置までもが引き継がれてしまう。
例えば、ファイルマネージャーアプリのように一つの画面でListのItemをクリックして、フォルダ階層を移動するような機能の場合、パスが変わればスクロール位置は先頭に来るのが自然だ。そして、画面回転の際には現在のスクロール位置が保存されるのがUIとして望ましい。
しかし、rememberLazyListStateでインスタンスを取得しては、リストの内容に関わらず、スクロール位置は保存・復元されてしまう。LaunchedEffectなどの副作用も利用して、スクロール位置をリセットするような処理を実装しても画面回転の再には必ず1度実行されてしまうため、これでは画面回転時に現在のスクロールを保存したいという要件には合致しない。要は画面回転で発火しない、再コンポーズ時のワンショットイベントがあれば実装できる。
別に対した機能でもないし幾らでも実装可能だが、Composeにおいて再Compose時(画面回転を含まない)のワンショットなイベントについては、様々な議論が為されている。
SharedFlowを用いる事はワンショットイベントの実装としてはアンチパターンと述べている記事や
Listとして現在のイベントを保持しておき、その都度の消費するようなデザインパターンを提唱する記事もある。
正直、どれで実装しようがSharedFlowやStateFlowがワンショットイベントとして利用可能なだけで正解ではないと思う。Composable関数の冪等性の理念からして、ワンショットイベントという副作用自体が間違いなのかもしれない。しかし、現実のユースケースではワンショットなイベントが必要とされる場面は多々ある。公式が〇〇Effectの形で画面回転時には発火しない副作用を実装してくれたら楽なのにと思った。