android
Firebase Ream-Time Database Paging 처리
android by kotlin
2022. 10. 25. 18:29
Firebase Real-Time Database 에서 데이터를 읽어와서 RecyclerView 또는 ViewPager2 에 데이터를 연결할 때 고려해야 하는 부분 중 서버에서 데이터를 한번에 읽어오지않고 사용자의 스크롤 지점에 따라서 조금씩 읽어오는 방식으로 하는 것이 좋습니다. 예를들어 서버에 저장된 Post 가 총 100개라고 하면 앱을 실행하면 최초로 10개만 받아오고 사용자가 스크롤하여서 앞으로 보여줄 아이템이 3~4개 정도 남아있을 때 다시 10개를 받아오는 방식으로 한다면 사용자에게 쾌적한 앱 서비스를 제공하는데 도움이 됩니다.
이 글에서는 Firebase Real-Time Database 를 사용하여 Paging 처리하는 방법에 대해 작성합니다.
1. 로딩한 데이터를 보여줄 ViewPager 를 초기화합니다.
private fun initTodayLogsViewPager() {
binding.todayLogsViewpager.adapter = todayLogsAdapter
binding.todayLogsViewpager.setPageTransformer(ZoomOutPageTransformer())
binding.todayLogsViewpager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
//현재까지 가져온 아이템의 마지막 인덱스 - (현재 보이는 아이템의 포지션 - 2) 일 때
//즉 마지막 아이템 2개가 남았을 때 Firebase 에 추가 요청합니다.
if(position == viewModel.todayLogs.value?.lastIndex?.minus(2)) {
if(!viewModel.isFetching) {
viewModel.fetchMore()
}
}
}
})
//최초로 보여줄 아이템을 요청합니다.
viewModel.fetchDayLogs()
}
2. use case 를 호출하여 Firebase 에 데이터를 요청합니다.
fun fetchMore() {
viewModelScope.launch {
//동일한 아이템에 대해 여러번 호출되는 것을 방지하기 위한 플래그입니다.
isFetching = true
val index = _todayLogs.value?.lastIndex
//Firebase 에 추가 데이터를 요청할 때 가장 마지막으로 받은 데이터의 key 값을 전달합니다.
//이 key 값 이후의 값만 받아오기 위한 용도입니다.
val response = fetchMoreDayLogsUseCase(todayLogs.value?.get(index!!)?.key.toString())
_todayLogs.value?.let {
val temp = it
it.addAll(response)
_todayLogs.value = temp
}
isFetching = false
}
}
3. usecase 에서는 Firebase 에 데이터를 요청 후 받아오고 받아온 데이터를 앱에서 사용할 형태로 변환하여 반환합니다.
class FetchDayLogsUseCase {
suspend operator fun invoke(): MutableList<DayLog> {
val response = Repository.fetchDayLogs()
val dayLogs = mutableListOf<DayLog>()
for(item in response.children) {
item.getValue(DayLog::class.java)?.let { dayLogs.add(it) }
}
return dayLogs
}
}
4. Firebase Real-Time Database 에 데이터를 요청합니다.
orderByKey() 를 통해 우선 하위 노드들을 정렬합니다. 그리고 startAfter() 에 최근 가장 마지막으로 읽어온 데이터의 key 값을 넣어주면 그 이후의 데이터부터 읽어올 수 있습니다. 마지막으로 limitToFirst() 를 통해 몇개의 데이터를 읽어올 지 결장합니다.
suspend fun fetchMoreDayLogs(key: String): DataSnapshot {
val response: DataSnapshot
withContext(Dispatchers.IO) {
Log.d("fetchMoreUseCase", key.toString())
response = Firebase.database.reference.child(Constant.LOGS_NODE).child("2022-10-25").orderByKey().startAfter(key).limitToFirst(4).get().await()
}
return response
}