페이징 라이브러리가 UI에 표시하기 위해 더 많은 항목을 가져올 때 더 많은 데이터를 가져오고 있음을 사용자에게 알리는 것이 좋습니다.
페이징 라이브러리는 CombinedLoadState 유형을 사용하여 로드 상태에 쉽게 액세스할 수 있는 방법을 제공합니다.
CombinedLoadState 인스턴스는 페이징 라이브러리에서 데이터를 로드하는 모든 구성 요소의 로드 상태를 설명합니다.
ArticlePagingSource의 LoadState에만 관심이 있으므로 주로 CombinedLoadState.source 필드의 LoadStates 유형을 사용합니다.
PagingDataAdapter 및 PagingDataAdapter.loadStateFlow를 통해 CombinedLoadStates에 액세스할 수 있습니다.
※ 로드 상태를 설명하는 데 도움이 되는 세 가지 클래스는 CombinedLoadStates, LoadStates 및 LoadState입니다.
CombinedLoadState에는 LoadStates 인스턴스가 있고 LoadStates는 LoadState 인스턴스를 제공합니다.
CombinedLoadStates.source는 LoadStates 유형이며 세 가지 유형의 LoadState 필드가 있습니다.
- LoadStates.append: 사용자의 현재 위치에서 검색할 항목의 LoadState용
- LoadStates.prepend: 사용자의 현재 위치 이전에 검색된 항목의 LoadState용
- LoadStates.refresh: 초기 로드 시 LoadState용
각 LoadState 자체는 다음 중 하나일 수 있습니다.
- LoadState.Loading: 항목 로드 중
- LoadState.NotLoading: 기사가 로드되지 않았습니다.
- LoadState.Error: 로드 오류가 발생했습니다.
여기서 중요한 점은 LoadState가 LoadState.Loading이라는 것입니다.
이는 ArticlePagingSource에 오류 사례가 포함되어 있지 않기 때문입니다.
먼저 UI의 상단과 하단에 진행률 표시줄을 추가하여 가져오기의 로드 상태를 양방향으로 표시합니다.
activity_articles.xml에서 다음과 같이 두 개의 LinearProgressIndicator 막대를 추가합니다.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.ArticleActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="0dp"
android:layout_height="0dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/prepend_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/append_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
이제 PagingDataAdapter에서 LoadStatesFlow를 수집하고 CombinedLoadState에 반응합니다.
ArticleActivity.kt의 상태를 수집합니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
articleAdapter.loadStateFlow.collect {
binding.prependProgress.isVisible = it.source.prepend is Loading
binding.appendProgress.isVisible = it.source.append is Loading
}
}
}
lifecycleScope.launch {
...
}
마지막으로 ArticlePagingSource에 지연을 추가하여 로드합니다.
private const val LOAD_DELAY_MILLIS = 3_000L
class ArticlePagingSource : PagingSource<Int, Article>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Article> {
val start = params.key ?: STARTING_KEY
val range = startKey.until(startKey + params.loadSize)
if (start !
= STARTING_KEY) delay(LOAD_DELAY_MILLIS)
return ...
}
지금까지 다룬 내용을 간략히 요약하면 다음과 같습니다.
- 페이지 매김과 페이지 매김이 필요한 이유에 대해 간단히 살펴봅니다.
- 호출기를 만들고 PagingSource를 정의하고 PagingData를 내보내 앱에 페이지 매김을 추가합니다.
- cachedIn 연산자를 사용하여 ViewModel의 캐시 PagingData
- PagingDataAdapter와 함께 UI에서 PagingData 사용
- PagingDataAdapter.loadStateFlow를 사용하여 CombinedLoadStates로 돌아가기