1. PagingDataAdapter을 알아보기 전에 Paging에 대해서 알아보자
페이징은 많은 데이터를 한꺼번에 가지고 오는방식이 아닌 리스너를 통해서 다음 페이지를 요청하면 서버나 내부저장소를 통해서 일정량의 데이터를 가지고 오는방식으로 시스템리소스를 줄일 수 있다. 그냥 구현을 할 수도 있지만 이것을 편하게 해주는 라이브러리라고 한다.
위의 PagingSource와 RemoteMediator ,Pager,PagingData가 무엇인지 알아야함
1)PagingData
한 번의 Load에 의해 만들어지는 페이징 데이터들의 컨테이너임. 한 번에 5개를 가져오면 그 5개를 하나의 페이징 데이터로 만든다?(아닌가?)
2) PagingSource(RxPagingSource :RxJava를 사용하게 되면 이걸로 사용)
로컬 데이터베이스나 서버 데이터베이스에서 데이터를 가져옴. pagingData를 load한다. 이미 로드된 페이징 데이터는 업데이트가 안되므로 업데이트시에는 새로운 페이징소스와 페이징데이터가 필요하다.
(1) Load Page : 페이징 소스에서 페이징 데이터를 가져온다.
(2) Updata Page : 페이징 소스를 업데이트 해줘야하므로 새로운 페이징 소스가 생성되어야한다.
( 페이징 소스가 업데이트 될때마다 새로 불러준다면 채팅방 같은 데이터에는 안어울듯?..)
PagingSource 는 abstract로 정의되있는 Load를 구현해 주어야하는데 이를 통해 서버나 데이터 베이스에 접근하여
LoadResult<Key, Value>를 반환한다.
override suspend fun load(
params: LoadParams<Int>
): LoadResult<Int, User> {
try {
// Start refresh at page 1 if undefined.
val nextPageNumber = params.key ?: 1
val response = backend.searchUsers(query, nextPageNumber)
return LoadResult.Page(
data = response.users,
prevKey = null, // Only paging forward.
nextKey = response.nextPageNumber
)
} catch (e: Exception) {
// Handle errors in this block and return LoadResult.Error if it is an
// expected error (such as a network failure).
}
}
위와 같이 reponse에서 데이터들을 받아와서 return 해주는 방식 으로 파이어베이스를 쓰는 나는 저기에 파이어 베이스와 연결을 하면될 듯.
3) Pager
페이징 데이터를 reactive stream하게 만들어 준다. 앞서 언급했듯이 페이징 데이터는 업데이트가 이루어지면 새로운 페이징 데이터로 바뀌어야한다. PagingSource.invalidate ,AsyncPagingDataDiffer.refresh, PagingDataAdapter.refresh를
통해서 Pager는 새로운 PagingSource와 PagingData가 바뀐다는 것을 알 수 있음.
4) RemoteMediator
RemoteMediator은 네트워크에서 페이지 데이터를 가져와서 Ui로 연결하는 것이 아니라 Room과 같은 데이터베이스에 저장한다. 이는 Ui에 데이터를 연결해주는 PagingSource랑은 다름.
이것도 Load를 구현해 주어야함.
2. PagingDataAdapter도 위와 같은 과정에 들어가는 데이터가 PagingData이면 된다.
PagindData를 제공하는 Repository와 ViewModel을 보자
우선 Repository
class UnsplashRepository @Inject constructor(private val service: UnsplashService) {
fun getSearchResultStream(query: String): Flow<PagingData<UnsplashPhoto>> {
return Pager(
config = PagingConfig(enablePlaceholders = false, pageSize = NETWORK_PAGE_SIZE),
pagingSourceFactory = { UnsplashPagingSource(service, query) }
).flow
}
companion object {
private const val NETWORK_PAGE_SIZE = 25
}
}
이렇게 구성되어 있다. 이 페이징 데이터를 뷰모델에서 adapter으로 보내주면 된다.
@HiltViewModel
class GalleryViewModel @Inject constructor(
private val repository: UnsplashRepository
) : ViewModel() {
private var currentQueryValue: String? = null
private var currentSearchResult: Flow<PagingData<UnsplashPhoto>>? = null
fun searchPictures(queryString: String): Flow<PagingData<UnsplashPhoto>> {
currentQueryValue = queryString
val newResult: Flow<PagingData<UnsplashPhoto>> =
repository.getSearchResultStream(queryString).cachedIn(viewModelScope)
currentSearchResult = newResult
return newResult
}
}
프래그먼트 단에서 다음과 같이 사용
private fun search(query: String) {
// Make sure we cancel the previous job before creating a new one
searchJob?.cancel()
searchJob = lifecycleScope.launch {
viewModel.searchPictures(query).collectLatest {
adapter.submitData(it)
}
}
}
나름의 결론)
페이징 데이터를 사용하려면 이미 존재하는 데이터 풀에서 가져오는 기능은 편할 것 같지만, 실시간으로 새로운 데이터가 추가되고 보여줘야하는 상황에서는 라이브데이터를 사용하는 ListAdapter를 사용하는게 편할 것 같다.
내가 msg가 저장되고 보여지는 샘플을 만들면서 어떻게 하면 기존의 페이징데이터는 그대로 있으면서 새로들어온 실시간 데이터만 바꿀수 있을까 고민을 해봤지만 답이없는듯..
doojuns-ordinary.tistory.com/44?category=995354
1. paging3 와 Room연결해서 사용해보기
SunFlower을 분석하면서 하나씩 따라해보는게 좋겠다 싶어서 테스트 프로젝트를 만들어본다. doojuns-ordinary.tistory.com/42?category=994822 1. DI 종속성 주입 (sunflower 분석 ,hilt, dagger) DI Dependency..
doojuns-ordinary.tistory.com
'안드로이드 jetpack > sunflower' 카테고리의 다른 글
6.liveData를 사용해 보자(Viewmodel 적용기) (0) | 2021.05.04 |
---|---|
5. work에 대해서 알아보자 (0) | 2021.05.02 |
3.recyclerview(ListAdapter) (0) | 2021.05.02 |
2.sunflower분석 ( hilt) (0) | 2021.04.29 |
1. DI 종속성 주입 (sunflower 분석 ,hilt, dagger) (0) | 2021.04.29 |