在 Jetpack Compose 中,如何具体处理 paging3 中的错误并显示在 ui 上?
In Jetpack Compose, how do I specifically handle errors in paging3 and display them on ui?
在我的例子中,我请求 GitHub API,如果我请求大量数据,我可能会收到 403 错误,而如果我 运行请求的数据,GitHub 将 return 我一个 422 不可处理的实体。所以我想根据这个在UI提示用户是被API限速还是没有新数据
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, EventWithRepoInfo> {
val position = params.key ?: GITHUB_STARTING_PAGE_INDEX
return try {
val receivedEvents = network.receivedEvents(token, network.getUserInfo(token).login, position, params.loadSize)
val eventWithRepoInfo: MutableList<EventWithRepoInfo> = mutableListOf()
val nextKey = if (receivedEvents.isEmpty()) {
null
} else {
position + (params.loadSize / NETWORK_PAGE_SIZE)
}
nextKey?.let {
receivedEvents.forEach {
eventWithRepoInfo.add(EventWithRepoInfo(it, ktorClient.getRepoInfo(token, it.repo.url)))
}
}
LoadResult.Page(
data = eventWithRepoInfo,
prevKey = if (position == GITHUB_STARTING_PAGE_INDEX) null else position - 1,
nextKey = nextKey
)
} catch (exception: IOException) {
exception.printStackTrace()
return LoadResult.Error(exception)
} catch (exception: HttpException) {
exception.printStackTrace()
return LoadResult.Error(exception)
}
}
所以我想判断这个地方是403还是422。如果是422会显示没有更多数据,403会提示用户api限速
LazyColumn {
events.apply {
when {
loadState.append is LoadState.Loading -> {
item {
Text("loading")
}
}
}
// I want to show different things here depending on different error codes
loadState.append is LoadState.Error -> {
item {
LargeButton(onClick = { events.retry() }) {
Text("loading error, retry.")
}
}
}
}
}
}
这里有很多东西,如果你真的想使用分页的力量(所以,只在用户滚动时加载项目),你需要使用 LazyColumn 提供的 items
方法,即接受参数 a LazyPagingItems<T>
首先,您应该从寻呼机中检索 PagingData 流。
val githubPager = Pager(...)
val pagingItems : Flow<PagingData<MyCustomDto>> = githubPager.flow
一旦获得分页数据流,理想情况下,您应该将其缓存在视图模型范围内,然后将其公开给视图
val cachedPagingItems = pagingItems.cachedIn(viewModelScope)
在你的内部是可组合的,你现在可以收集 pagingItems,将错误传输到你的视图模型,并在你的 LazyColumn 中显示分页数据
我做了一个小的扩展函数来执行remember操作,直接暴露一个重试块:
@Composable
fun <T : Any> Flow<PagingData<T>>.collectAndHandleState(
handleLoadStates: (LoadStates, () -> Unit) -> Job
): LazyPagingItems<T> {
val lazyPagingItem = collectAsLazyPagingItems()
// Handle the different load state event
val pagingLoadStates = lazyPagingItem.loadState.mediator ?: lazyPagingItem.loadState.source
LaunchedEffect(pagingLoadStates) {
handleLoadStates(pagingLoadStates)
}
return lazyPagingItem
}
要使用此扩展功能,请在内部进行组合:
// Get our paging items
val pagingItems = viewModel.cachedPagingItems.collectAndHandleState(viewModel::handleLoadState)
LazyColumn {
item {
// Display an error if any, or any informative message here, coming from an UiState exposed by you're view model
}
// Display the items
items(pagingItems) { pagedItem ->
// The composable you want to display
}
}
在你的视图模型中,一个简单的函数:
fun handleLoadState(loadStates: LoadStates, retry: () -> Unit): Job {
// Handle the different load state, find the error or loading ones and update you're ui state
// To rapidly find an error you can do :
val errorLoadState = arrayOf(
loadStates.append,
loadStates.prepend,
loadStates.refresh
).filterIsInstance(LoadState.Error::class.java).firstOrNull()
// And then check the error by getting the associated throwable
val throwable = errorLoadState?.error
}
我在第 206 行的惰性行中处理了服务器错误
Github
有一种简单的方法可以找出发生了什么类型的错误,希望下面的代码对您有所帮助。
events.apply {
when {
/** Showing error state */
loadState.refresh is LoadState.Error -> {
val e = loadState.refresh as LoadState.Error
val message = ""
if (e.error is UnknownHostException) {
message = // Your message
} else if (e.error is /*Exception*/){
message = // Your message
}
item {
ErrorView(message)
}
}
/** Showing error state */
loadState.append is LoadState.Error -> {
val e = loadState.refresh as LoadState.Error
val message = ""
if (e.error is UnknownHostException) {
message = // Your message
} else if (e.error is /*Exception*/){
message = // Your message
}
item {
ErrorView(message)
}
}
}
}
在我的例子中,我请求 GitHub API,如果我请求大量数据,我可能会收到 403 错误,而如果我 运行请求的数据,GitHub 将 return 我一个 422 不可处理的实体。所以我想根据这个在UI提示用户是被API限速还是没有新数据
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, EventWithRepoInfo> {
val position = params.key ?: GITHUB_STARTING_PAGE_INDEX
return try {
val receivedEvents = network.receivedEvents(token, network.getUserInfo(token).login, position, params.loadSize)
val eventWithRepoInfo: MutableList<EventWithRepoInfo> = mutableListOf()
val nextKey = if (receivedEvents.isEmpty()) {
null
} else {
position + (params.loadSize / NETWORK_PAGE_SIZE)
}
nextKey?.let {
receivedEvents.forEach {
eventWithRepoInfo.add(EventWithRepoInfo(it, ktorClient.getRepoInfo(token, it.repo.url)))
}
}
LoadResult.Page(
data = eventWithRepoInfo,
prevKey = if (position == GITHUB_STARTING_PAGE_INDEX) null else position - 1,
nextKey = nextKey
)
} catch (exception: IOException) {
exception.printStackTrace()
return LoadResult.Error(exception)
} catch (exception: HttpException) {
exception.printStackTrace()
return LoadResult.Error(exception)
}
}
所以我想判断这个地方是403还是422。如果是422会显示没有更多数据,403会提示用户api限速
LazyColumn {
events.apply {
when {
loadState.append is LoadState.Loading -> {
item {
Text("loading")
}
}
}
// I want to show different things here depending on different error codes
loadState.append is LoadState.Error -> {
item {
LargeButton(onClick = { events.retry() }) {
Text("loading error, retry.")
}
}
}
}
}
}
这里有很多东西,如果你真的想使用分页的力量(所以,只在用户滚动时加载项目),你需要使用 LazyColumn 提供的 items
方法,即接受参数 a LazyPagingItems<T>
首先,您应该从寻呼机中检索 PagingData 流。
val githubPager = Pager(...)
val pagingItems : Flow<PagingData<MyCustomDto>> = githubPager.flow
一旦获得分页数据流,理想情况下,您应该将其缓存在视图模型范围内,然后将其公开给视图
val cachedPagingItems = pagingItems.cachedIn(viewModelScope)
在你的内部是可组合的,你现在可以收集 pagingItems,将错误传输到你的视图模型,并在你的 LazyColumn 中显示分页数据
我做了一个小的扩展函数来执行remember操作,直接暴露一个重试块:
@Composable
fun <T : Any> Flow<PagingData<T>>.collectAndHandleState(
handleLoadStates: (LoadStates, () -> Unit) -> Job
): LazyPagingItems<T> {
val lazyPagingItem = collectAsLazyPagingItems()
// Handle the different load state event
val pagingLoadStates = lazyPagingItem.loadState.mediator ?: lazyPagingItem.loadState.source
LaunchedEffect(pagingLoadStates) {
handleLoadStates(pagingLoadStates)
}
return lazyPagingItem
}
要使用此扩展功能,请在内部进行组合:
// Get our paging items
val pagingItems = viewModel.cachedPagingItems.collectAndHandleState(viewModel::handleLoadState)
LazyColumn {
item {
// Display an error if any, or any informative message here, coming from an UiState exposed by you're view model
}
// Display the items
items(pagingItems) { pagedItem ->
// The composable you want to display
}
}
在你的视图模型中,一个简单的函数:
fun handleLoadState(loadStates: LoadStates, retry: () -> Unit): Job {
// Handle the different load state, find the error or loading ones and update you're ui state
// To rapidly find an error you can do :
val errorLoadState = arrayOf(
loadStates.append,
loadStates.prepend,
loadStates.refresh
).filterIsInstance(LoadState.Error::class.java).firstOrNull()
// And then check the error by getting the associated throwable
val throwable = errorLoadState?.error
}
我在第 206 行的惰性行中处理了服务器错误 Github
有一种简单的方法可以找出发生了什么类型的错误,希望下面的代码对您有所帮助。
events.apply {
when {
/** Showing error state */
loadState.refresh is LoadState.Error -> {
val e = loadState.refresh as LoadState.Error
val message = ""
if (e.error is UnknownHostException) {
message = // Your message
} else if (e.error is /*Exception*/){
message = // Your message
}
item {
ErrorView(message)
}
}
/** Showing error state */
loadState.append is LoadState.Error -> {
val e = loadState.refresh as LoadState.Error
val message = ""
if (e.error is UnknownHostException) {
message = // Your message
} else if (e.error is /*Exception*/){
message = // Your message
}
item {
ErrorView(message)
}
}
}
}