前人未踏の領域へ Androidアプリ開発編

Androidアプリ開発に関する調査メモ置き場。古い記事にはアプリ以外も含まれます。

Jetpack Compose:LazyColumnのスクロール位置が先頭に戻ってしまう

内容

Paging3とLazyColmnを使用して一覧を表示しているが、画面遷移して戻るとスクロール位置が先頭に戻ってしまう。どうすれば良いか

補足

以前同じ問題を対処するため以下の記事を書いたが、不完全だったのと個人的により良い方法が見つかったため改めて。

Android: Fragment内のComposeでスクロール位置を復元する - 前人未踏の領域へ Androidアプリ開発編

原因

こちらのIssueTrackerに記載のあるように、LazyColumnブロック内にitemsの他に itemがあるとその情報をもとにStateが上書きされてしまい、データが失われてしまうらしい。

https://issuetracker.google.com/issues/177245496?pli=1

対応

「lazyPagingItemsの件数が0件かつitemが存在する」場合にスクロールの復元ができなくなるので、その間はitemの表示が行われないようにする。

val loadState = lazyPagingItems.loadState
LazyColumn( state = listState ) {
    if (loadState.append.endOfPaginationReached && lazyPagingItems.itemCount == 0) {
       // データなしの場合NoData()コンポーサブルを表示
       item {
          NoData()
       }
    } else if  (lazyPagingItems.itemCount > 0) {
        // データが1件以上ある場合はヘッダーを表示
        item {
            Header()
        }
    }
    items(items = lazyPagingItems){
       // 一覧のアイテムを表示
    }
    
    // Footerがある場合も同様にデータ取得完了後に表示する必要あり
    if (loadState.append is LoadState.Loading) {
        item {
            Footer()
        }
    } 
}

備考

こちらは回避策であり、そもそも collectAsLazyPagingItems()が必ずデータ0で初期化されてしまうところに問題があるようだ。バグの修正が待たれる。