使用Compose来开发WanAndroidApp碰到的一些问题集锦
2023-05-25
2 min read
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 ->
//...
}
}
}