Kar*_*eek 2 android android-mvvm android-paging android-jetpack-compose android-paging-3
我正在开发一个 Android Compose 项目,其中使用 Paging 3 和 LazyColumn 来显示从网络调用获取的项目列表。Paging 3 的默认行为是根据prefetchDistance用户滚动来加载页面,但在我的例子中,它会加载大约 15 个页面,每个页面在屏幕启动时包含 10 条记录。我尝试过将其设置prefetchDistace为 10,但不起作用。
这是我的代码: ViewModel
class ShowAllNotificationsViewModel @Inject constructor(private val pagingSource: NotificationPagingSource) :
BaseViewModel() {
private val _uiState =
MutableStateFlow<UIState<BaseResponseModel<NotificationResponseModel?>>>(UIState.StateLoading)
val uiState = _uiState.asStateFlow()
private val _isRefreshing = MutableStateFlow(false)
val isRefreshing = _isRefreshing.asStateFlow()
val items: Flow<PagingData<NotificationModel>> = Pager(
config = PagingConfig(
pageSize = 10,
prefetchDistance = 5,
enablePlaceholders = false,
),
pagingSourceFactory = { pagingSource }
)
.flow
.cachedIn(viewModelScope)
fun refreshData() {
pagingSource.invalidate()
}
}
Run Code Online (Sandbox Code Playgroud)
分页来源:
class NotificationPagingSource @Inject constructor(val requestNotificationsUseCase: GetNotificationsUseCase) :
PagingSource<String, NotificationModel>() {
override suspend fun load(params: LoadParams<String>): LoadResult<String, NotificationModel> {
Timber.e(IllegalStateException())
Timber.d("load params = $params")
val responseModel = requestNotificationsUseCase(params.key)
val result = responseModel?.getAsResult();
result?.let {
return@load when (result) {
is Result.Error<*>,
Result.Loading,
is Result.SessionTimeoutError<*> -> {
LoadResult.Error(
SessionTimeoutException()
)
}
is Result.Success -> {
LoadResult.Page(
result.value.data?.notifications ?: listOf(),
prevKey = null,
nextKey = result.value.data?.lastId,
)
}
}
}
return LoadResult.Error(
IllegalStateException()
)
}
override fun getRefreshKey(state: PagingState<String, NotificationModel>): String? {
Timber.d("getRefreshKey = state = $state")
return null
}
}
Run Code Online (Sandbox Code Playgroud)
用户界面:
@Composable
fun ShowAllNotificationCompose(items: LazyPagingItems<NotificationModel>) {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Black)
) {
Timber.d("ShowAllNotificationCompose : state = ${items.loadState}")
HeaderCompose()
Box(
modifier = Modifier
.weight(1f)
) {
val listState = rememberLazyListState()
LazyColumn(
modifier = Modifier,
state = listState
) {
items(
count = items.itemCount,
key = {
items[it]?.id ?: 0
}
) {
val notificationModel = items[it]
if (notificationModel != null) {
NotificationItem(item = notificationModel)
} else {
NotificationShimmerItem()
}
}
if (items.loadState.append == LoadState.Loading) {
items(2) {
NotificationShimmerItem()
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法修改此设置以确保仅在到达prefectchDistance. 提前致谢。
问题出在你的key:
key = { items[it]?.id ?: 0 }
Run Code Online (Sandbox Code Playgroud)
当您调用LazyPagingItems::get它时,它会通知 Paging 项目访问,这可以触发页面加载。来自文档:
返回指定位置处呈现的项目,通知 Paging 项目访问以触发满足 prefetchDistance 所需的任何加载。
并且key立即为所有项目调用 ,而不仅仅是在显示它们时。所以对于 key,你应该使用该peek函数。或者您可以使用itemKey,它在内部使用 peek 。
key = { items.peek(it)?.id ?: 0 }
key = items.itemKey { it.id }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
138 次 |
| 最近记录: |