feat(chat): Talk 탭에 RecyclerView 스크롤 페이지네이션 추가
- /api/chat/room/list 호출에 page 파라미터 적용 (0부터 시작) - ViewModel에 currentPage/lastPageReached 상태 추가 및 append 로직 구현 - Fragment에 스크롤 리스너로 바닥 근접 시 다음 페이지 자동 로드 - 빈 데이터 시 마지막 페이지로 간주하여 추가 로딩 중단
This commit is contained in:
@@ -23,7 +23,8 @@ import retrofit2.http.Query
|
||||
interface TalkApi {
|
||||
@GET("/api/chat/room/list")
|
||||
fun getTalkRooms(
|
||||
@Header("Authorization") authHeader: String
|
||||
@Header("Authorization") authHeader: String,
|
||||
@Query("page") page: Int
|
||||
): Single<ApiResponse<List<TalkRoom>>>
|
||||
|
||||
@POST("/api/chat/room/create")
|
||||
|
||||
@@ -29,8 +29,8 @@ class TalkTabFragment : BaseFragment<FragmentTalkTabBinding>(
|
||||
setupRecyclerView()
|
||||
observeViewModel()
|
||||
|
||||
// 데이터 로드
|
||||
viewModel.loadTalkRooms()
|
||||
// 데이터 로드 (스크롤 페이지네이션: 0페이지부터 시작)
|
||||
viewModel.refreshTalkRooms()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
@@ -78,8 +78,24 @@ class TalkTabFragment : BaseFragment<FragmentTalkTabBinding>(
|
||||
})
|
||||
|
||||
recyclerView.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
val lm = LinearLayoutManager(requireContext())
|
||||
layoutManager = lm
|
||||
adapter = this@TalkTabFragment.adapter
|
||||
|
||||
// 스크롤 로딩 리스너: 끝에 도달하면 다음 페이지 로드
|
||||
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
if (dy <= 0) return // 아래로 스크롤할 때만 체크
|
||||
|
||||
val totalItemCount = lm.itemCount
|
||||
val lastVisible = lm.findLastVisibleItemPosition()
|
||||
val threshold = 3 // 바닥 3개 전에서 미리 로드
|
||||
if (totalItemCount > 0 && lastVisible >= totalItemCount - 1 - threshold) {
|
||||
viewModel.loadNextPage()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.chat.talk
|
||||
|
||||
class TalkTabRepository(private val api: TalkApi) {
|
||||
fun getTalkRooms(
|
||||
token: String
|
||||
) = api.getTalkRooms(authHeader = token)
|
||||
token: String,
|
||||
page: Int
|
||||
) = api.getTalkRooms(authHeader = token, page = page)
|
||||
}
|
||||
|
||||
@@ -20,25 +20,51 @@ class TalkTabViewModel(private val repository: TalkTabRepository) : BaseViewMode
|
||||
val toastLiveData: LiveData<String?>
|
||||
get() = _toastLiveData
|
||||
|
||||
fun loadTalkRooms() {
|
||||
private var currentPage: Int = 0
|
||||
private var lastPageReached: Boolean = false
|
||||
|
||||
/**
|
||||
* 초기화 후 첫 페이지를 로드한다. page는 0부터 시작한다.
|
||||
*/
|
||||
fun refreshTalkRooms() {
|
||||
currentPage = 0
|
||||
lastPageReached = false
|
||||
_talkRooms.value = emptyList()
|
||||
loadNextPage()
|
||||
}
|
||||
|
||||
/**
|
||||
* 다음 페이지를 로드한다. 빈 데이터를 반환하면 마지막 페이지로 간주한다.
|
||||
*/
|
||||
fun loadNextPage() {
|
||||
if (_isLoading.value == true || lastPageReached) return
|
||||
_isLoading.value = true
|
||||
val token = "Bearer ${SharedPreferenceManager.token}"
|
||||
compositeDisposable.add(
|
||||
repository.getTalkRooms(token = "Bearer ${SharedPreferenceManager.token}")
|
||||
repository.getTalkRooms(token = token, page = currentPage)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{ response ->
|
||||
_isLoading.value = false
|
||||
if (response.success) {
|
||||
_talkRooms.value = response.data ?: emptyList()
|
||||
val newItems = response.data ?: emptyList()
|
||||
if (newItems.isEmpty()) {
|
||||
// 마지막 페이지 도달
|
||||
lastPageReached = true
|
||||
} else {
|
||||
val current = _talkRooms.value.orEmpty()
|
||||
_talkRooms.value = current + newItems
|
||||
currentPage += 1
|
||||
}
|
||||
} else {
|
||||
_toastLiveData.value =
|
||||
response.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
}
|
||||
},
|
||||
{
|
||||
{ throwable ->
|
||||
_isLoading.value = false
|
||||
it.message?.let { message -> Logger.e(message) }
|
||||
throwable.message?.let { message -> Logger.e(message) }
|
||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user