Jetpack Compose 保存LazyColumn/LazyRow列表状态

4,780 阅读2分钟

问题复现

使用Paging3加载分页数据,并显示到页面A的LazyColumn上,往上滑动LazyColumn,然后navigation.navigate跳转到页面B,接着再navigatUp回到页面A,页面A的LazyColumn变成从第一(0)项数据开始显示。

1.gif

问题出现的原因

22.png

LazyColumn的第二个参数state:LazyListState = rememberLazyListState()可以用于记录“状态”,但这个“状态”没有做持久化保存。

解决方法

一般情况下

只需要为LazyColumn/LazyRow创建这个用于记录状态的变量并且持久化保存起来就可以了。

44.png

55.png

66.png

这么写也行 77.png

LazyColumn/LazyRow和指示器联动

联动的情况下,点击指示器Index之后调用lazyListState.scrollToItem(0, 0)来重置LazyColumn的状态,如果有必要的话可以根据指示器的count来创建List LaztListState以保存多个状态。

由于项目结构的原因,demo中的“项目”页面和“公众号”页面需要设定触发条件才执行lazyListState.scrollToItem(0, 0)

202020.png

效果图

2.gif

解析LazyListState

99.png

  • LazyListState有个带参的构造函数,这两个参数的默认值都为0,看命名都可以知道分别为列表第一个可见的Item的索引和列表第一个可见的Item的偏移量。

3.gif

  • LazyListState内有三个比较重要的变量,scrollPosition、firstVisibleItemIndex、firstVisibleItemScrollOffset,分别是当前滚动的位置、获取当前滚动位置的索引(观察者)、获取当前滚动位置的偏移量(观察者)

1010.png

  • 随着用户的滑动,会不断触发update方法,update方法内会更新indexState和scrollOffsetState,而observableIndexob和servableScrollOffset的get方法分别获取到的就是indexState和scrollOffsetState,也就是firstVisibleItemIndex、firstVisibleItemScrollOffset的值。

16.png 另外,在LazyColumn内调用的LazyList的方法内,用于计算当前可见项和偏移量的变量是lazyListState.firstVisibleItemIndexNonObservable和lazyListState.firstVisibleItemScrollOffsetNonObservable,它们就是在LazyListState的updata方法中保存的索引和偏移量。

1212.png

项目地址

PlayAndroid