본문 바로가기

안드로이드

paging Library, pagedList, pagedListAdapter

paging Library는 android architecture component(aac)의 일부로 recyclerview에서 대용량 데이터를 로드하고 표시하는데 도움이 되는 라이브러리이다. 즉 앱이 데이터 소스로부터 필요한 정보를 점진적으로 읽어오는 작업을 쉽게 만들어주는 라이브러리로, 디바이스에 과부하가 걸리거나, 큰 데이터베이스로부터의 쿼리를 기다리지 않도록 만들어준다.

페이징 : 데이터를 일정한 데이터로 나누는 것을 의미한다. 

기존의 Android API는 콘텐츠의 페이징을 허용했지만 중요한 제약 조건과 단점이 있었다.

  • CursorAdapter는 데이터베이스의 쿼리결과를 ListView의 항목들에 쉽게 매핑시켜주었지만, 데이터베이스 쿼리를 UI 스레드에서 하는것과 Cursor를 이용하기 때문에 데이터의 페이징을 비효율적으로 하는 단점이었다. 더 많은 정보를 확인하려면 Large Database Queries on Android 블로그 글을 확인한다.
  • AsyncListUtil은 RecyclerView에서 포지션 기반의 페이징을 허용하지만, 포지션 기반이 아닌 페이징은 허용하지 않는다. 또한, 셀수 있는 데이터셋에서 null을 플레이스 홀더로 강제로 사용한다.

새로운 페이징 라이브러리는 이러한 문제들을 해결한다.

서버 - 클라이언트 모델에서는 서버에서 페이지을 구현하는것이 일반적이다. 예를 들어 구글검색에서 안드로이드를 검색하면 28억개의 검색결과를 다 클라이언트에게 보여주지 않고 상위 10개만 보여준다. rest api는 사용자가 열람할 정보만 가져올수 있도록 만들어준다. get /users?since=135

안드로이드 앱 페이징 기법은 두 가지가 존재한다. 

1. 무한 스크롤링 기법 2. 모바일웹처럼 1,2,3 페이지를 나누는 기법

안드로이드 앱의 기존의 페이징 기법은 다음과 같다. 

사용자가 앱을 스크롤하여 어느정도 범위에 도달하게 되면 다음 페이지를 호출하여 데이타를 받아온 뒤에 새로운 항목을 추가한다. 

단점

1. recyclerview 스크롤시 아이템을 다루는 법이 필요하다. 

2. 스크롤방향, 이미 페이지가 로딩중인지, 더이상 불러올페이지가 없는지 체크해야 된다. 

3. 공식적인 가이드가 부재하다. -적지않는 시행착오

4. 다음 페이지 호출시점을 알아내기 위한 UI처리에 집중

PagingLibrary는 pagedList, DataSource, PagedListAdapter로 이루어져 있다. 

pagedList는 일종의 LazyedList이며 필요치 않는 메모리 적재이슈를 피할수있다. 

지연로딩을 지원하며 청크(덩어리) 단위로 로딩하며 필요시에만 데이터를 로딩한다.

datasource는 pagedList에 데이터를 제공하는 제공자이다. (백그라운드 스레드제공)

1. PageKeyedDatasource - 인접페이지에 대한 정보가 내려올때 사용된다. cursor기반의 페이징(페이스북, 트위터)을 처리해주는 rest api에 적합하다. (로드할 데이터가 다음 / 이전 키를 포함)

2. ItemKeyedDatasource - 현재리스트의 마지막 요소을 이용해 다음페이지를 불러오는 페이징(항목 N의 데이터를 이용해 N+1의 데이터를 가져와야 한다)

3. PositionalDatasource - 페이지번호, 오프셋을 이용해 특정페이지를 바로 요청한다. (데이터 저장소에서 선택한 위치로부터 데이터의 페이지를 가져와야한다)

pagedListAdapter는 클래스는 PagedList로부터 데이터를 UI에 나타내기 위한 RecyclerView.Adapter의 구현체이다. 예를들어, 새로운 페이지가 로드되었을 때, PagedListAdapter는 데이터가 갱신되었음을 RecyclerView에게 알려준다. 이는 RecyclerView가 실제 항목으로 플레이스홀더를 대체하도록 하여 적절한 애니메이션을 수행할 수 있다.

또한 PagedListAdapter는 백그라운드 스레드를 사용하여 한 PagedList에서 다른 PagedList 로의 변경 사항을 계산하고 (예 : 데이터베이스 변경이 업데이트 된 데이터로 새 PagedList를 생성하는 경우) 필요에 따라 목록 내용을 업데이트하기 위해 notifyItem ... () 메소드를 호출한다. 그리고나서 RecyclerView는 필요한 변화를 수행한다. 예를들어, PagedList 버전사이에 항목들의 위치가 변경되면, RecyclerView는 해당 항목을 새로운 위치로 애니메이션으로 움직인다.

RxpagedlistBuilder, LivePagedListBuilder는 리스트의 수정,삭제가 발생되는 상황에서 Datasource의 invalidate함수가 호출되면 새로운 pagedList와 datasource를 자동으로 생성처리해준다. 

1. RxpagedListBuilder : RxJava2 기반의 기능을 제공한다.  PagedList를 구현할 때 Flowable과 Observable을 생성할 수 있다.

Flowable<PagedList<Item>> pagedItems = RxPagedListBuilder(myDataSource, /* page size */ 50) .setFetchScheduler(myNetworkScheduler) .buildFlowable(BackpressureStrategy.LATEST);

2. LivePagedListBuilder  : LiveData<PagedList>를 생성한다. 

LiveData<PagedList<Item>> pagedItems = LivePagedListBuilder(myDataSource, /* page size */ 50) .setFetchExecutor(myNetworkExecutor) .build();