정말 너무 편리한 라이브러리지만 이것도 꽤나 날 고생시켰다🤯
까먹지 않고 머릿 속에 남겨두기 위해 정리를 해본당
Paging 3
- Paging 라이브러리를 사용하면 로컬 저장소나 네트워크를 통해 큰 데이터를 나누어 효율적으로 로드하고 표시할 수 있음
- 이 방식을 사용하면 앱에서 네트워크 대역폭과 시스템 리소스를 모두 더 효율적으로 사용할 수 있음
- Paging3 라이브러리의 구성요소는 권장 Android 앱 아키텍처에 맞게 설계되었으며 다른 Jetpack 구성요소와 원활하게 통합됨
장점
- 페이징 된 데이터에 대한 메모리 내 캐싱을 지원 -> 앱이 페이징 된 데이터로 작업하는 동안 시스템 리소스를 효율적으로 사용할 수 있음
- 요청 중복 제거가 내장되어 있어 앱이 네트워크 대역폭과 시스템 리소스를 효율적으로 사용할 수 있음
- 사용자가 로드된 데이터를 끝까지 스크롤 할 때 구성 가능한 RecyclerView 어댑터가 자동으로 데이터를 요청
- 코틀린 코루틴과 Flow를 우선적으로 지원하며, LiveData 및 RxJava를 지원
- 새로고침 및 재시도 기능을 포함하여 오류 처리를 기본으로 지원
아키텍처
- Repository 레이어
- ViewModel 레이어
- UI 레이어
Repository 레이어
- Repository 레이어의 기본 페이징 라이브러리 구성요소는
PagingSource
- 각 PagingSource 객체는 데이터 소스와 이 소스에서 데이터를 검색하는 방법을 정의
- PagingSource 객체는 네트워크 소스 및 로컬 데이터베이스를 포함한 단일 소스에서 데이터를 로드할 수 있음
- 사용할 수 있는 다른 페이징 라이브러리 구성요소는 RemoteMediator가 있음
RemoteMediator
객체는 로컬 데이터베이스 캐시가 있는 네트워크 데이터 소스와 같은 계층화된 데이터 소스의 페이징을 처리
ViewModel 레이어
Pager
구성요소는 PagingSource 객체 및 PagingConfig
구성 객체를 바탕으로 반응형 스트림에 노출되는 PagingData 인스턴스를 구성하기 위한 공개 API를 제공
- ViewModel 레이어를 UI에 연결하는 구성요소는
PagingData
- PagingData 객체는 페이지로 나눈 데이터의 스냅샷을 보유하는 컨테이너로 PagingSource 객체를 쿼리하여 결과를 저장
UI 레이어
- UI 레이어의 기본 페이징 라이브러리 구성요소는 페이지로 나눈 데이터를 처리하는 RecyclerView 어댑터인
PagingDataAdapter
- AsyncPagingDataDiffer 구성요소를 사용하여 고유한 맞춤 어댑터를 빌드할 수 있습니다.
주요 클래스
PagingSource
- 네트워크 또는 데이터베이스에서 페이징 데이터를 로드하는 추상 클래스
- 이를 구현하려면 페이지 key 타입을 정의해야 함
- 데이터를 검색하는 방법을 정의하는 클래스
- PagingSource에서 로드된 데이터는 PagingData 인스턴스로 관리됨
- PagingData는 데이터가 추가적으로 로드됨에 따라 커질 수 있지만 기존에 로드된 데이터는 갱신되지 않음
- load()에서 실제 데이터를 가져오는 로직 구현 (prevkey, nextKey를 다룸)
- getRefreshKey()에서 초기 key값이나 데이터 로드 중단 후 재 로드시 이전 position에서 중단된 key값을 가져오는 등 load에서 사용할 key 값을 가져오는 로직 구현
- 네트워크 및 로컬 데이터베이스에서 페이징 데이터를 로드하는 역할
- RemoteMediator를 사용하게 되면 PagingSource는 캐시된 데이터만을 사용하여 UI처리용 데이터를 처리
- RemoteMediator 사용 시 특이점은 Key를 내부에서 제공해주거나 사용하지 않음
- PagingSource 객체 및 PagingConfig 객체를 바탕으로 반응형 스트림을 생성
- 각 PagingData는 페이징 된 데이터 스냅샷을 나타내며, Pager로부터 Flow, Observable, LiveData 형태를 반환합니다.
PagingConfig
- Pager 객체를 생성할 때 필수적으로 필요한 요소로 페이징을 구성하는 방법을 정의
- 페이징 하는 데이터의 크기, placeholder 사용 유무 등 PagingSource를 구성하는 방법을 정의합니다.
- 로드 대기 시간, 초기 로드의 크기 요청 등 PagingSource에서 콘텐츠를 로드하는 방법에 관한 옵션 설정
- 정의해야 하는 유일한 필수 매개변수는 각 페이지에 로드해야 하는 항목 수를 가리키는 페이지 크기
- 기본적으로 Paging은 로드하는 모든 페이지를 메모리에 유지 -> PagingConfig에서 maxSize 매개변수를 설정하면 스크롤 시에 메모리를 낭비하지 않을 수 있음
- PagingConfig.pageSize는 여러 화면의 항목이 포함될 만큼 충분히 커야 함 (페이지가 너무 작으면 해당 페이지 콘텐츠가 전체 화면을 가리지 않기 때문에 목록이 깜박일 수 있음)
- 기본적으로 PagingConfig.maxSize는 무제한이므로 페이지가 삭제되지 않음 -> 페이지를 삭제하기 위해서는 네트워크 요청이 많이 발생하지 않도록 maxSize를 크게 설정해야 함
PagingData
- 페이징 된 데이터를 담아두는 컨테이너
- PagingSource 객체를 쿼리 하여 결과를 저장하며, 최종적으로 반환되는 데이터는 일반적으로 UI layer의 PagingDataAdapter가 전달받게 됨
PagingDataAdapter
- RecyclerView에 데이터를 표시하는 주된 UI 구성 요소
- PagingData를 입력받아 내부적으로 언제 데이터를 추가해야 할지 관찰하게 됨
- 백그라운드 스레드에서 DiffUtil을 사용하여 데이터를 정제한 뒤에 데이터를 로드하기 때문에 UI 스레드에서 새로운 항목을 추가할 때 부드럽게 나타낼 수 있음
정리
PadingSource 또는 RemoteMediator가 Pager를 통해 PagingConfig에 있는 정보를 가지고 PagingData를 생성 -> 이를 PagingDataAdapter가 활용해 UI에 정보를 나타냄
예제
안드로이드 MVVM 패턴 연습 프로젝트
참조