2

I am recently migrate to Paging3. However, I noticed that most of the tutorials and guides are mainly on normal pagination (from top to bottom).

I need to implement the REVERSE pagination as user scroll to top boundary, will load for page 2,3,4.. Is there any tutorial/guide for this?

PS: Now the initial loading is working fine, but when I scroll to top-most, I have no idea how to load Page 2 data.

My current approach

PagingSource

class ChatPagingSource(
    private val apiService: ApiService,
    private val roomId: String
): PagingSource<Int, Message>() {

    override fun getRefreshKey(state: PagingState<Int, Message>): Int? = null

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Message> {
        return try{
            val page = params.key?: 1
            val pageSize = params.loadSize

            val call = apiService.getMessageFeedPaging(
                room_id = roomId,
                page = page,
                max = pageSize,
                exclude = EXCLUDE_TYPE
            )
            val repoItems = call.messages
            val prevKey = if(page > 1) page - 1 else null
            val nextKey = if(repoItems.isNotEmpty()) page + 1 else null

            if(repoItems.isNotEmpty()) {
                val messageList = mutableListOf<Message>()
                for (i in repoItems) {
                    val replyData = Converters.convertReplyDataAPItoReplyData(i.reply_data)

                    val msg = Converters.convertMessageAPItoMessage(replyData, i, hasError = false)
                    messageList.add(msg)
                }
                LoadResult.Page(messageList, prevKey, nextKey)
            } else {
                LoadResult.Page(listOf(), prevKey, nextKey)
            }
        }catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

}

Repository

 fun loadRemoteMessageStream(roomId: String): LiveData<PagingData<Message>> {
        return Pager(
            config = PagingConfig(20),
            pagingSourceFactory = { ChatPagingSource(apiService, roomId) }
        ).liveData
    }


ViewModel

 private val _remoteMessage = chatRepository.loadRemoteMessageStream(currentRoomId)
        .cachedIn(viewModelScope)
        .let { it as MutableLiveData<PagingData<Message>> }

val remoteMessage: LiveData<PagingData<Message>> = _remoteMessage

Fragment

 chatViewModel.remoteMessage.observe(viewLifecycleOwner, {
            chatAdapter.submitData(viewLifecycleOwner.lifecycle, it)
  })
Teo
  • 876
  • 9
  • 22

1 Answers1

0

In case this helps anyone, I will post out my own answer. The key is to reverse prevKey and nextKey and fixed the pageSize that your API required (in my case is 20).

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Message> {
    val pageSize = 20
    val prevKey = if(repoItems.isNotEmpty()) page + 1 else null
    val nextKey = if(page > 1) page - 1 else null
}

Then, in the recyclerview, you should use stackFromEnd = true so that initially the recyclerview will auto-scroll to bottom.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Teo
  • 876
  • 9
  • 22