Paging 라이브러리는 페이징된 데이터의 로드 요청 상태를 추적하고 노출합니다.
LoadState 클래스를 통해
각
LoadType 및 데이터 소스 유형(
PagingSource 또는
RemoteMediator)마다 별도의 LoadState 신호가 제공됩니다. 리스너에서 제공하는
CombinedLoadStates
객체는 이러한 모든 신호의 로드 상태에 관한 정보를 제공합니다. 이 세부정보를 사용하여 사용자에게 적절한 로드 표시기를 표시할 수 있습니다.
로드 상태
Paging 라이브러리는 LoadState 객체를 통해 UI에서 사용할 로드 상태를 노출합니다. LoadState 객체는 현재 로드 상태에 따라 다음 세 가지 형식 중 하나를 취합니다.
- 활성 로드 작업이 없고 오류가 없는 경우
LoadState는LoadState.NotLoading객체입니다. 이 서브클래스에는 페이지로 나누기의 끝에 도달했는지를 나타내는endOfPaginationReached속성이 포함됩니다. - 활성 로드 작업이 있는 경우
LoadState는LoadState.Loading객체입니다. - 오류가 있는 경우
LoadState는LoadState.Error객체입니다.
LazyPagingItems 래퍼의 loadState 속성을 통해 이러한 상태에 액세스합니다. 이 상태는 기본 콘텐츠 공개 상태를 처리하거나 (예: 전체 화면 새로고침 스피너) 로드 항목을 LazyColumn 스트림에 직접 삽입하는 (예: 바닥글 스피너) 두 가지 방법으로 사용할 수 있습니다.
리스너로 로드 상태에 액세스하기
UI에서 로드 상태를 모니터링하려면 loadState 속성
에서 제공하는 LazyPagingItems 래퍼를 사용하세요. 이렇게 하면 새로고침, 추가 또는 삽입 이벤트의 로드 동작에 반응할 수 있는
CombinedLoadStates 객체가 반환됩니다.
다음 예에서 UI는 새로고침 (초기) 로드의 현재 상태에 따라 로드 스피너 또는 오류 메시지를 표시합니다.
@Composable fun UserListScreen(viewModel: UserViewModel) { val pagingItems = viewModel.flow.collectAsLazyPagingItems() Box(modifier = Modifier.fillMaxSize()) { // Show the list content LazyColumn { items(pagingItems.itemCount) { index -> UserItem(pagingItems[index]) } } // Handle the loading state when (val state = pagingItems.loadState.refresh) { is LoadState.Loading -> { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } is LoadState.Error -> { ErrorButton( message = state.error.message ?: "Unknown error", onClick = { pagingItems.retry() }, modifier = Modifier.align(Alignment.Center) ) } else -> {} // No separate view needed for success/not loading } } }
LazyPagingItems에 관한 자세한 내용은 큰 데이터 세트 (페이징)를 참고하세요.
로드 헤더 및 바닥글 추가
목록의 시작 또는 끝에 로드 표시기를 표시하려면 (헤더 또는 바닥글 역할을 함) LazyColumn 범위 내에서 이러한 상태를 위한 전용 항목 블록을 추가하세요.
`CombinedLoadStates` 객체를 사용하여 헤더의 삽입 상태와
바닥글의 추가 상태를 모니터링할 수 있습니다.
다음 예에서 목록은 더 많은 데이터를 가져오는 경우 목록 하단에 진행률 표시줄 또는 재시도 버튼을 표시합니다.
@Composable fun UserList(viewModel: UserViewModel) { val pagingItems = viewModel.pager.flow.collectAsLazyPagingItems() LazyColumn { // 1. Header (Prepend state) // Useful if you support bidirectional paging or jumping to the middle item { val prependState = pagingItems.loadState.prepend if (prependState is LoadState.Loading) { LoadingItem() } else if (prependState is LoadState.Error) { ErrorItem( message = prependState.error.message ?: "Error", onClick = { pagingItems.retry() } ) } } // 2. Main Data items(pagingItems.itemCount) { index -> UserItem(pagingItems[index]) } // 3. Footer (Append state) // Shows when the user scrolls to the bottom and more data is loading item { val appendState = pagingItems.loadState.append if (appendState is LoadState.Loading) { LoadingItem() } else if (appendState is LoadState.Error) { ErrorItem( message = appendState.error.message ?: "Error", onClick = { pagingItems.retry() } ) } } } } @Composable fun LoadingItem() { Box(modifier = Modifier.fillMaxWidth().padding(16.dp), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } @Composable fun ErrorItem(message: String, onClick: () -> Unit) { Column( modifier = Modifier.fillMaxWidth().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = message, color = Color.Red) Button(onClick = onClick) { Text("Retry") } } }
추가 로드 상태 정보에 액세스하기
앞의 예에서와 같이 pagingItems.loadState.refresh를 호출하는 것이 편리합니다. 그러나 로컬
데이터베이스 (PagingSource)와
네트워크 (RemoteMediator)에서 로드하는 것의 차이를 가립니다.
이렇게 하면 캐시된 데이터를 즉시 사용할 수 있는 경우에도 캐시된 데이터
를 즉시 사용할 수 있는 경우에도 UI에 로드 스피너가 잠시 표시될 수 있습니다.
로컬 데이터베이스가 비어 있고 네트워크 동기화가 활성 상태일 때만 로드 스피너를 표시하는 것과 같은 정밀한 제어를 위해서는 구성 가능한 함수 내에서 source 및 mediator 속성에 직접 액세스하세요.
val loadState = pagingItems.loadState val isSyncing = loadState.mediator?.refresh is LoadState.Loading val isLocalEmpty = loadState.source.refresh is LoadState.NotLoading && pagingItems.itemSnapshotList.items.isEmpty() if (isSyncing && isLocalEmpty) { FullScreenLoading() } else { UserList(pagingItems) if (isSyncing) { TopOverlaySpinner() } }
로드 상태 변경에 관한 반응
새로고침이 완료될 때 목록의 맨 위로 스크롤하거나 Snackbar를 표시하는 등 로드 상태 변경에 따라 일회성 부수 효과를 트리거해야 할 수 있습니다.
LaunchedEffect 내에서 snapshotFlow를 사용하여 상태 변경을 스트림으로 관찰합니다. 이렇게 하면 Flow 연산자를 적용하여 특정 이벤트를 격리할 수 있습니다.filterdistinctUntilChanged
val listState = rememberLazyListState() LaunchedEffect(pagingItems) { // 1. Convert the state to a Flow snapshotFlow { pagingItems.loadState.refresh } // 2. Filter for the specific event (Refresh completed successfully) .distinctUntilChanged() .filter { it is LoadState.NotLoading } .collect { // 3. Trigger the side effect listState.animateScrollToItem(0) } }
추가 리소스
Paging 라이브러리 및 로드 상태에 관한 자세한 내용은 다음 리소스를 참고하세요.
문서
콘텐츠 보기
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- Paging 라이브러리 개요