Android/이슈 처리

[Android] An instance of PagingSource was re-used ···

O_Gyong 2023. 3. 17.

기존 프로젝트에서 Hilt를 적용을 위해 코드를 수정하였는데 Paging3  Adapter의 refresh() 호출 시 앱이 죽는 현상이 발생했다.

 

java.lang.IllegalStateException: An instance of PagingSource was re-used when Pager expected to create a new instance. Ensure that the pagingSourceFactory passed to Pager always returns a new instance of PagingSource.

 

에러의 내용은 Pager가 새로운 인스턴스를 만들 때 PagingSource의 인스턴스를 재사용한다는 것이다.

 


문제가 되는 코드는 아래와 같았다.

 

Repository

@Singleton
class ImageViewRepository @Inject constructor(private val imageViewPagingSource: ImageViewPagingSource) {
    fun getImageViewPagingSource(): Flow<PagingData<ImageViewData>> {
        return Pager(
            config =  PagingConfig(
                pageSize = 10,
                enablePlaceholders = false
            ),
            pagingSourceFactory = { imageViewPagingSource }
        ).flow
    }
}

 

PagingSource

@Singleton
class ImageViewPagingSource @Inject constructor(private val database: ImageViewDatabase): PagingSource<Int, ImageViewData>() {
    override fun getRefreshKey(state: PagingState<Int, ImageViewData>): Int? {
        println("getRefreshKey $state")
        return state.anchorPosition?.let { anchorPosition ->
            state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1)
                ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1)
        }
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ImageViewData> {
        val page = params.key ?: STARTING_PAGE
        return try {
            var data: List<ImageViewData>? = null

            database.withTransaction {
             data = database.imageViewDao().getAll(page)
            }

            LoadResult.Page(
                data = data!!,
                prevKey = if (page == STARTING_PAGE) null else page-1,
                nextKey = if(data.isNullOrEmpty()) null else page+1
            )
        } catch (e: IOException) {
            LoadResult.Error(e)
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}

 

Repository에서 Hilt를 적용하면서 Pager를 반환할 때  PagingSource의 인스턴스가 재사용되고 있었다.

 

PagingSource의 새 인스터스가 반환되도록 코드를 수정하면서 해결했다.

(ImageViewPagingSource에서는 @Singleton 주석을 제거함)

 

@Singleton
class ImageViewRepository @Inject constructor(private val database: ImageViewDatabase) {
    fun getImageViewPagingSource(): Flow<PagingData<ImageViewData>> {
        return Pager(
            config =  PagingConfig(
                pageSize = 10,
                enablePlaceholders = false
            ),
            pagingSourceFactory = { ImageViewPagingSource(database) }
        ).flow
    }
}

댓글