본문 바로가기

Android + Kotlin

[Android+kotlin] PagingDataAdapter 에서 삭제기능 구현하기

반응형

이전 개발 코드에서 PagingDataAdapter와 DataSource를 이용하여 paging 리스트를 구현한 부분이 있었습니다.

그런데, 게시물 상세화면에서 삭제시, 목록 갱신(adapter.refresh()) 를 하게되는데, 페이징 했던 페이지까지 표시되지 않는 문제가 있었습니다.

확인해보니, DataSource 클래스에 getRefeshKey()를 무조건 return 0으로 해서 발생한 이슈였습니다.

(만들다 말았나봅니다. 아님 귀찮았던가....;;)

처음에는 일반 리스트와 같이 adapter의 items에서 removed를 해주고, notifyItemRemoved()를 해주려고 했으나, PagingDataAdapter 의 items는 snapshot()으로 가져와야 하고, List<> 클래스를 사용하기때문에 삭제가 불가했습니다.

 

위와 같은 이유로 서버에 갱신된 목록을 요청하는 방법으로 개발 방향을 잡았습니다.


 

수정 방향은

1. 삭제시 adapter.refresh() 호출

2. DataSource 클래스에서 getRefreshKey() 호출시 param으로 전달되는 state를 확인하여, 요청할 페이지 학인

3. load() 함수에서 LoadParams가 Refresh 클래스인지 여부를 확인하여, 서버에 요청할 아이템 개수 계산하여 요청

 

위와같이 개발할 예정입니다.

그럼, 개발을 시작해 봅시다~!!


 

1. 게시물 삭제 후에 adapter.refresh()를 호출합니다.

 

2. DataSource클래스의 getRefreshKey() 함수를 아래와 같이 구현합니다.

override fun getRefreshKey(state: PagingState<Int, ISectionMoreItem>): Int? {
    return state.anchorPosition?.let { anchorPosition ->
        state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1)?: 
        state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1)
    }
}

파라메터로 전달된 status의 anchorPosition 값으로 prevKey 또는 nextKey 값으로 refresh할 페이지를 찾을 수 있습니다.


 

3. 이어서 DataSource 클래스에 load() 함수가 호출됩니다.

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ISectionMoreItem> {
        return try {
            var page: Int = params.key ?: 0
            var size = 20
            var nextPage: Int? = page + 1

            when(params) {
                is LoadParams.Refresh -> {
                    if(page > 0) {
                        size = (page + 1) * 20
                    }
                    page = 0
                }
                else -> {}
            }

            val response = {API 호출 함수}(
                page = page,
                size = size
            )
            val originalContentCount = response.contents?.count() ?: 0
            val result: MutableList<{데이터클래스}> = response.contents

			if(originalContentCount < 20) {
                nextPage = null
            }
            LoadResult.Page(
                data = result,
                nextKey = nextPage,
                prevKey = null
            )
        } catch (e: Exception) {
            e.printStackTrace()
            LoadResult.Error(e)
        }
    }

파라메터로 들어오는 LoadParams가 Refresh 클래스인지, Append 클래스인지를 확인하여 처리합니다.

Refresh 클래스가 목록을 새로 갱신할때 들어오는 클래스이므로, 해당 클래스일때 page값을 확인하여 서버에 요청할 item 의 개수(size)를 계산해 줍니다.

(페이징할때는 여러번에 나눠 가져왔던 페이지도, Refresh 페이지가 몇페이지 뒤라면 그만큼을 한번에 요청해야 refresh 해줄수 있습니다.)

그리고, 다음 페이지 값(nextPage)도 함께 계산해 놓습니다.

완료 후에 다음 페이지 key(nextKey) 값으로 전달합니다.


 

위의 코드를 실행하면 여러 페이지를 넘어가서 아이템 삭제를 하더래도, 현재 위치에 머물면서 삭제한 아이템만 쏙! 사라지게 됩니다.

반응형