使用Compose来开发WanAndroidApp碰到的一些问题集锦

1.LzayCloumn页面重新展示的时候出现重新定位到顶部的问题

1.1问题场景:

使用Pagin加载分页数据,并显示在A的LazyColumn上,向下滑动LazyColumn,然后通过navigation.navigate跳转到页面B,接着再navigatUp回到页面A,页面A的LazyColumn又回到列表顶部。

1.2分析:

LazyColumn默认的参数state是有通过rememberLazyListState()来做持久化保存的。如果LazyColumn内部只包含一个items来创建子列表的话,那么是没有问题的,如果是内部通过item来创建了Header活着Footer就不行了。
这是因为rememberLazyListState会在列表中至少有一项时restore滚动位置,同时Paging是通过Flow获取数据的,当返回到页面重组时并不能马上获取到Paging数据,第一帧时Paging的itemCount为0
但同时因为LazyColumn中已经有了一个Header,这时便会还原保存的位置,但因为这时Paging中的数据还为空,不能滚动到正确的位置,于是便又滚动到顶部了
而当LazyColumn中没有Header时,列表中至少有一项时便是Paging数据成功填充的时候,这个时候还原的位置就是对的,所以没有问题。

1.3解决问题:

既然原因在于LazyListState没有在正确的时机被还原,那我们将LazyListSate保存在ViewModel中,并且在Paging中有数据时再还原listState,如下所示:

@HiltViewModel
class SquareViewModel @Inject constructor(
    private var service: HttpService,
) : ViewModel() {
    private val pager by lazy { simplePager { service.getSquareData(it) }.cachedIn(viewModelScope) }
    val listState: LazyListState = LazyListState()
}
 
@Composable
fun SquarePage(
    navCtrl: NavHostController,
    scaffoldState: ScaffoldState,
    viewModel: SquareViewModel = hiltViewModel()
) {
    val squareData = viewStates.pagingData.collectAsLazyPagingItems()
    // 当`Paging`有数据时,返回`ViewModel`中的`listState`
    val listState = if (squareData.itemCount > 0) viewStates.listState else LazyListState()
 
    RefreshList(squareData, listState = listState) {
        itemsIndexed(squareData) { _, item ->
           //...
        }
    }
}