Paging 3으로 이전

Paging 3은 이전 Paging 라이브러리 버전과 크게 다릅니다. 이 버전은 Paging 2 사용 시 겪는 일반적인 어려움을 해결하고 기능을 향상했습니다. 앱이 이미 이전 버전의 Paging 라이브러리를 사용하는 경우 이 페이지를 참고하여 Paging 3으로 이전하는 방법을 자세히 알아보세요.

Paging 3이 앱에서 사용하는 첫 Paging 라이브러리 버전인 경우에는 페이징된 데이터 로드 및 표시에서 기본 사용법 정보를 확인하세요.

Paging 3으로 이전하여 얻을 수 있는 이점

Paging 3에는 이전 버전의 라이브러리에 없는 다음 기능이 포함되어 있습니다.

  • Kotlin 코루틴 및 Flow를 위한 최고 수준의 지원 제공
  • RxJava Single 또는 Guava ListenableFuture 프리미티브를 사용한 비동기 로드 지원
  • 재시도 및 새로고침 기능을 포함하여 반응형 UI 디자인을 위한 로드 상태와 오류 신호가 내장됨
  • 취소 지원 및 간소화된 데이터 소스 인터페이스를 포함하여 저장소 레이어가 개선됨
  • 프레젠테이션 레이어, 목록 구분자, 맞춤 페이지 변환, 로드 상태 머리글 및 바닥글이 개선됨

Paging 3으로 앱 이전

Paging 3으로 완전히 이전하려면 Paging 2의 세 가지 주요 구성요소를 모두 이전해야 합니다.

  • DataSource 클래스
  • PagedList
  • PagedListAdapter

그러나 Paging 3의 일부 구성요소는 이전 버전의 Paging과 호환됩니다. 특히 Paging 3의 PagingSource API는 이전 버전의 LivePagedListBuilderRxPagedListBuilder를 위한 데이터 소스가 될 수 있습니다. 마찬가지로 Pager API는 asPagingSourceFactory() 메서드에 이전 DataSource 객체를 사용할 수 있습니다. 즉, 다음과 같은 이전 옵션이 있습니다.

  • DataSourcePagingSource로 이전하되 Paging 구현의 나머지 부분은 변경하지 않고 그대로 유지할 수 있습니다.
  • PagedListPagedListAdapter를 이전하되 이전 DataSource API를 계속 사용할 수 있습니다.
  • 전체 Paging 구현을 이전하여 앱을 Paging 3으로 완전히 이전할 수 있습니다.

이 페이지의 섹션에서는 앱의 각 레이어에서 Paging 구성요소를 이전하는 방법을 설명합니다.

DataSource 클래스

이 섹션에서는 PagingSource를 사용하기 위해 이전 Paging 구현을 이전하는 데 필요한 변경사항을 모두 설명합니다.

Paging 2의 PageKeyedDataSource, PositionalDataSource, ItemKeyedDataSource가 모두 Paging 3의 PagingSource API로 결합됩니다. 모든 이전 API 클래스의 로드 메서드는 PagingSource에서 단일 load() 메서드로 결합됩니다. 이전 API 클래스의 구현에서는 여러 로드 메서드에서 많은 로직이 동일한 경우가 많기 때문에, 단일 메서드로 결합됨으로써 코드 중복이 줄어듭니다.

모든 로드 메서드 매개변수는 Paging 3에서 각 로드 유형의 서브클래스를 포함하는 LoadParams 봉인 클래스로 대체됩니다. load() 메서드에서 로드 유형을 구별해야 하는 경우 어떤 LoadParams 서브클래스(LoadParams.Refresh, LoadParams.Prepend, LoadParams.Append)가 전달되었는지 확인하세요.

PagingSource 구현에 관한 자세한 내용은 데이터 소스 정의를 참고하세요.

새로고침 키

PagingSource의 구현은 로드된 페이지된 데이터의 중간에서 새로고침을 다시 시작하는 방법을 정의해야 합니다. state.anchorPosition을 최근에 액세스한 색인으로 사용하여 정확한 초기 키를 매핑하기 위해 getRefreshKey()를 구현하면 됩니다.

Kotlin

// Replaces ItemKeyedDataSource.
override fun getRefreshKey(state: PagingState): String? {
  return state.anchorPosition?.let { anchorPosition ->
    state.getClosestItemToPosition(anchorPosition)?.id
  }
}

// Replacing PositionalDataSource.
override fun getRefreshKey(state: PagingState): Int? {
  return state.anchorPosition
}

Java

// Replaces ItemKeyedDataSource.
@Nullable
@Override
String getRefreshKey(state: PagingState) {
  Integer anchorPosition = state.anchorPosition;
  if (anchorPosition == null) {
    return null;
  }

  return state.getClosestItemToPosition(anchorPosition);
}

// Replaces PositionalDataSource.
@Nullable
@Override
Integer getRefreshKey(state: PagingState) {
  return state.anchorPosition;
}

Java

// Replacing ItemKeyedDataSource.
@Nullable
@Override
String getRefreshKey(state: PagingState) {
  Integer anchorPosition = state.anchorPosition;
  if (anchorPosition == null) {
    return null;
  }

  return state.getClosestItemToPosition(anchorPosition);
}

// Replacing PositionalDataSource.
@Nullable
@Override
Integer getRefreshKey(state: PagingState) {
  return state.anchorPosition;
}

목록 변환

이전 버전의 Paging 라이브러리에서는 페이징된 데이터를 변환하는 데 다음 메서드를 사용합니다.

  • DataSource.map()
  • DataSource.mapByPage()
  • DataSource.Factory.map()
  • DataSource.Factory.mapByPage()

Paging 3에서는 모든 변환이 PagingData의 연산자로 적용됩니다. 위의 목록에 있는 메서드를 사용하여 페이징된 목록을 변환하는 경우에는 새로운 PagingSource를 사용하여 Pager를 구성할 때 변환 로직을 DataSource에서 PagingData로 이동해야 합니다.

Paging 3을 사용하여 페이징된 데이터에 변환을 적용하는 방법을 자세히 알아보려면 데이터 스트림 변환을 참고하세요.

PagedList

이 섹션에서는 Paging 3에서 PagerPagingData를 사용하기 위해 이전 Paging 구현을 이전하는 데 필요한 변경사항을 모두 설명합니다.

PagedListBuilder 클래스

PagingData는 Paging 2의 기존 PagedList를 대체합니다. PagingData로 이전하려면 다음을 업데이트해야 합니다.

  • 페이징 구성이 PagedList.Config에서 PagingConfig로 이동했습니다.
  • LivePagedListBuilderRxPagedListBuilder가 단일 Pager 클래스로 결합되었습니다.
  • Pager.flow 속성을 사용하여 관찰 가능한 Flow<PagingData>를 노출합니다. RxJava 및 LiveData 변형도 확장 속성으로 사용할 수 있으며 정적 메서드를 통해 Java에서 호출할 수 있고 각각 paging-rxjava* 모듈과 paging-runtime 모듈에서 제공됩니다.

Kotlin

val flow = Pager(
  // Configure how data is loaded by passing additional properties to
  // PagingConfig, such as prefetchDistance.
  PagingConfig(pageSize = 20)
) {
  ExamplePagingSource(backend, query)
}.flow
  .cachedIn(viewModelScope)

Java

// CoroutineScope helper provided by the lifecycle-viewmodel-ktx artifact.
CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(viewModel);
Pager<Integer, User> pager = Pager<>(
  new PagingConfig(/* pageSize = */ 20),
  () -> ExamplePagingSource(backend, query));

Flowable<PagingData<User>> flowable = PagingRx.getFlowable(pager);
PagingRx.cachedIn(flowable, viewModelScope);

Java

// CoroutineScope helper provided by the lifecycle-viewmodel-ktx artifact.
CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(viewModel);
Pager<Integer, User> pager = Pager<>(
  new PagingConfig(/* pageSize = */ 20),
  () -> ExamplePagingSource(backend, query));

PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), viewModelScope);

Paging 3을 사용하여 PagingData 객체의 반응형 스트림을 설정하는 방법에 관한 자세한 내용은 PagingData 스트림 설정을 참고하세요.

계층화된 소스용 BoundaryCallback

Paging 3에서는 RemoteMediatorPagedList.BoundaryCallback을 대체하여 네트워크 및 데이터베이스에서 페이징하기 위한 핸들러로 사용됩니다.

Paging 3에서 RemoteMediator를 사용하여 네트워크 및 데이터베이스에서 페이징하는 방법에 관해 자세히 알아보려면 Android Paging Codelab을 참고하세요.

PagedListAdapter

이 섹션에서는 Paging 3의 PagingDataAdapter 또는 AsyncPagingDataDiffer 클래스를 사용하기 위해 이전 Paging 구현을 이전하는 데 필요한 변경사항을 모두 설명합니다.

Paging 3은 새로운 PagingData 반응형 스트림을 처리하기 위한 PagingDataAdapter를 제공합니다. 그러지 않으면 PagedListAdapterPagingDataAdapter의 인터페이스가 동일합니다. PagedListAdapter에서 PagingDataAdapter로 이전하려면 PagingDataAdapter를 대신 확장하도록 PagedListAdapter의 구현을 변경합니다.

PagingDataAdapter에 관한 자세한 내용은 RecyclerView 어댑터 정의를 참고하세요.

AsyncPagedListDiffer

현재 AsyncPagedListDiffer가 적용된 맞춤 RecyclerView.Adapter 구현을 사용 중이라면 대신 Paging 3에서 제공되는 AsyncPagingDataDiffer를 사용하도록 구현을 이전하세요.

Kotlin

AsyncPagingDataDiffer(diffCallback, listUpdateCallback)

Java

new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);

Java

new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);

추가 리소스

Paging 라이브러리에 관한 자세한 내용은 다음과 같은 추가 리소스를 참고하세요.

Codelab

샘플