일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- Kotlin
- 회원가입
- Android
- ListAdapter
- Jetpack
- 로그인
- 컴포즈
- UiState
- 코딩테스트
- MVVM
- 코틀린
- DiffUtil
- NavHost
- 뷰
- 리사이클러뷰
- 안드로이드
- Build variants
- 클린아키텍처
- coroutine
- XML
- Compose
- cleanarchitecture
- 알고리즘
- Flow
- Authentication
- sharedFlow
- NavController
- 커스텀뷰
- 파이어베이스
- 플레이스토어
- Today
- Total
Grusie 안드로이드 개발 기술 블로그
[Android] Paging 3.0 라이브러리 본문
페이징3 라이브러리란
Paging3는 JetPack 라이브러리 중 하나로, 데이터 소스로부터 데이터를 나누어 효과적으로 로딩 할 수 있게 해준다.
로컬 DB 혹은 네트워크에서 쉽게 데이터를 불러올 수 있도록 도와주기 때문에 개발 시간을 단축시켜 준다.
Paging3는 코틀린으로 우선 개발이 되고, 코루틴 및 Flow와 같은 새로운 방식의 비동기 작업으로 동작한다. 또한 RxJava와 LiveData도 지원한다.
페이징 라이브러리를 사용하여 얻을 수 있는 이점
- Paging된 데이터의 메모리 내 캐싱.
- 요청 중복 삭제 기능이 기본 제공되므로 앱에서 네트워크 대역폭과 시스템 리소스를 효율적으로 사용할 수 있다.
- 사용자가 로드된 데이터의 끝까지 스크롤 할 때 구성 가능한 RecyclerView 어댑터가 자동으로 데이터를 요청한다.
- Kotlin 코루틴 및 Flow뿐 아니라 LiveData 및 RxJava를 최고 수준으로 지원한다.
- 새로고침 및 재시도 기능을 포함하여 오류 처리를 기본으로 지원한다.
Paging3 아키텍처
Paging 라이브러리의 구성요소는 앱의 세 가지 레이어에서 작동한다.
- 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이다.
- 또는 포함된 AsyncPagingDateDiffer 구성요소를 사용하여 고유한 맞춤 어댑터를 빌드할 수 있다.
참고 : 앱에서 UI에 Compose를 사용하는 경우 Paging을 UI 레이어에 통합할 때 androidx.paging:paging-compose 아티팩트를 사용할 것.
주요 클래스 소개
Repository Layer
PagingData
- 페이징된 데이터의 Container 역할을 한다. 데이터가 새로고침 될 때마다 이에 상응하는 PagingData가 별도로 생성된다.
PagingSource
- 로컬 데이터베이스 또는 네트워크로 데이터를 불러오는 것을 담당하는 추상 클래스이다.
RemoteMediator
- 네트워크(Remote)에서 불러온 데이터를 로컬 데이터베이스에 캐시(Cache)하여 불러오는 것을 담당한다.
페이징 소스를 활용해 데이터를 로드하는 과정
ViewModel Layer
Pager
- Repository Layer에서 구현된 PagingSource와 함께 PagingData 인스턴스를 구성하는 반응형 스트림을 생성한다.
- PagingSource에서 데이터를 로드하는 방법, 옵션을 정의한 PagingConfig 클래스와 함께 사용된다.
UI Layer
PagingDataAdapter
- PagingData를 RecyclerView에 바인딩하기 위해 사용된다.
- 데이터를 어느 시점에서 더 받아올 것인가 등 UI와 관련된 대부분의 일을 책임진다.
실제 구현 코드
의존성 추가
dependencies {
def paging_version = "3.2.1"
implementation "androidx.paging:paging-runtime:$paging_version"
// alternatively - without Android dependencies for tests
testImplementation "androidx.paging:paging-common:$paging_version"
// optional - RxJava2 support
implementation "androidx.paging:paging-rxjava2:$paging_version"
// optional - RxJava3 support
implementation "androidx.paging:paging-rxjava3:$paging_version"
// optional - Guava ListenableFuture support
implementation "androidx.paging:paging-guava:$paging_version"
// optional - Jetpack Compose integration
implementation "androidx.paging:paging-compose:3.3.0-alpha03"
}
PagingSource
class TestPagingSource: PagingSource<Int, TestPagingData>() {
override fun getRefreshKey(state: PagingState<Int, TestPagingData>): Int? {
TODO("Not yet implemented")
}
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, TestPagingData> {
TODO("Not yet implemented")
}
}
- load() : 실제 데이터를 가져오는 로직을 구현하는 함수
- getRefreshKey() : 초기 key값이나, 데이터 로드 중단 후 로드 시 이전 position에서 중단된 key값을 가져오는 등 load에서 사용할 key값을 가져오는 로직구현을 위한 함수이다.
RemoteMediator
@OptIn(ExperimentalPagingApi::class)
class TestRemoteMediator: RemoteMediator<Int, TestPagingData>(){
override suspend fun initialize(): InitializeAction {
return InitializeAction.SKIP_INITIAL_REFRESH
}
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, TestPagingData>
): MediatorResult {
MediatorResult.Success(endOfPaginationReached = true)
}
}
- initallize() : 캐시된 데이터를 갱신시킬 것인지에 대한 로직 구현을 위한 함수
- load() : LoadType을 활용하여 데이터 추가로드 여부에 대한 로직을 구현한 뒤, 결과를 load함수의 반환형인 MediatorResult에 endOfPaginationReached 파라미터를 넘겨주어 데이터 로드를 끝마칠지 판단한다.
RemoteMediator 사용 시 특이점은 Key를 내부에서 제공해주거나 사용하지 않는다는 것이다.
(상황에 따라 key가 필요하다면 내부 DB를 사용하여 직접 생성 및 관리 하도록 한다.)
Pager
// PagerSource 사용
val pagingData: Flow<PagingData<TestPagingData>> = Pager(
config = PagingConfig(pageSize = 10)
) {
TestPagingSource()
//pagingSourceFactory
}.flow.cachedIn(viewModelScope)
// RemoteMediator 사용
val pagingDataFlow: Flow<PagingData<TestPagingData>> = Pager(
config = PagingConfig(pageSize = 10),
remoteMediator = TestRemoteMediator()
) {
TestPagingSource()
//pagingSourceFactory
}.flow
- PagingSource나, RemoteMediator에서 Pageconfig의 정보를 토대로 PagingData를 생성해서, 스트림화 해주는 클래스이다.
- 스트림화 시에, Flow, LiveData, RxJava 등의 유형들도 지원한다.
- Pager를 통해 스트림을 만들어, ViewModel을 통해서 사용하면 된다.
ViewModel
class TestViewModel(private val repository: TestRepository): ViewModel() {
//..
fun getContent(): Flow<PagingData<TestPagingData>> {
return repository.pagingData()
.cachedIn(viewModelScope)
}
}
- cachedIn() : CoroutineScope에서 데이터를 캐시할 수 있는 함수
View
class TestFragment : Fragment() {
//..
private fun initTest() {
//..
lifecycleScope.launch {
viewModel.getContent().collectLatest {
adapter.submitData(it)
}
}
}
- 뷰모델에서 생성한 데이터를 뷰에서, CollectLatest로 수집해 UI에 표현 해 주면 된다.
참고
https://developer.android.com/topic/libraries/architecture/paging/v3-overview?hl=ko
페이징 라이브러리 개요 | Android 개발자 | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 페이징 라이브러리 개요 Android Jetpack의 구성요소 Paging
developer.android.com
후기
- 페이징을 기존에는 리사이클러뷰의 스크롤 리스너를 달아서, LastVisibleItem을 확인해, 페이징을 진행하였으나, Paging3라이브러리를 활용하면, 에러처리, 새로고침 등 다양한 기능들을 활용하여 안정적으로 사용할 수 있다는 것을 알게되었다.
물론 코드가 복잡하고, 만약 RemoteMediator를 활용한다면, 키를 따로 저장하는 Local DB를 만들어야 할 수도 있으니 상황에 따라서, 사용하면 될 것 같다.
'안드로이드 개발 > 라이브러리' 카테고리의 다른 글
[Android]RxJava 사용하기 (0) | 2024.04.15 |
---|---|
[Android] Retrofit2 사용법 (0) | 2024.03.27 |
[Android] Compose + Paging 검색 기능 만들기(Flow - debounce) (1) | 2024.03.12 |
[Android] JetPack:Compose 네비게이션(navigation) - 2 (0) | 2024.03.07 |
[Android] JetPack:Compose 네비게이션(navigation) - 1 (0) | 2024.03.06 |