[Android] Paging Code

minnie_dev·2022년 1월 24일
0

Jetpack

목록 보기
12/12
post-thumbnail

1. 페이징 라이브러리 추가

implementation "androidx.paging:paging-runtime-ktx:3.1.0"

2. Model, API 정의

Post2.kt

data class Post2(
    @SerializedName("userId")
    val myUserId : Int,
    val id : Int,
    val title : String,
    val body : String
)

TestApi.kt

interface TestApi {
    @GET("posts")
    suspend fun getCustomPost2(
        @Query("userId") userId:Int,
        @Query("_sort") sort : String,
        @Query("_order") order : String
    ): Response<List<Post2>>
}

3. PagingSource 정의하기

MyPagingSource.kt

private const val STARTING_PAGE_IDX = 1

class MyPagingSource(
    private val testApi : TestApi,
    private val userId : Int) : PagingSource<Int, Post2>() {
    override fun getRefreshKey(state: PagingState<Int, Post2>): Int? {
        TODO("Not yet implemented")
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Post2> {
        return try {
            val position = params.key?: STARTING_PAGE_IDX
            val response = testApi.getCustomPost2(
                userId = userId,
                sort = "id",
                order = "asc"
            )

            val post = response.body()

            LoadResult.Page(
                data = post!!,
                prevKey = if(position== STARTING_PAGE_IDX) null else position-1,
                nextKey = position + 1
            )
        } catch (exception : IOException){
            LoadResult.Error(exception)
        } catch (exception : HttpException){
            LoadResult.Error(exception)
        }
    }

}

4. PagingData 스트림 설정

MyPagingRepository.kt

class MyPagingRepository {
    fun getPost(userId : Int) =
        Pager(
            config = PagingConfig(
                pageSize = 5,
                maxSize = 20,
                enablePlaceholders = false
            ),
            pagingSourceFactory = {MyPagingSource(RetrofitInstance.api,userId)}
        ).liveData
}

5. ViewModel

MainViewModel.kt

class MainViewModel (private val repository: MyPagingRepository) : ViewModel() {
    private val myCustomPost2 : MutableLiveData<Int> = MutableLiveData()

    val result = myCustomPost2.switchMap { queryString ->
        repository.getPost(queryString).cachedIn(viewModelScope)
    }

    fun searchPost(userId:Int){
        myCustomPost2.value = userId
    }
}

class MainViewModelFactory(private val repository: MyPagingRepository):ViewModelProvider.Factory{
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return MainViewModel(repository) as T
    }

}

6. PagingDataAdapter 정의

class MyAdapter
    : PagingDataAdapter<Post2, MyViewHolder>(IMAGE_COMPARATOR) {


    class MyViewHolder(private val binding:ItemLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(post:Post2){
            Log.d("Adapter","bind 됨 ${post.id}")
            binding.userIdText.text = post.myUserId.toString()
            binding.idText.text = post.id.toString()
            binding.titleText.text = post.title
            binding.bodyText.text = post.body
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val binding = ItemLayoutBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return MyViewHolder(binding)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem = getItem(position)
        if(currentItem!=null){
            holder.bind(currentItem)
        }
    }

    companion object {
        private val IMAGE_COMPARATOR = object : DiffUtil.ItemCallback<Post2>() {
            override fun areItemsTheSame(oldItem: Post2, newItem: Post2) =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Post2, newItem: Post2) =
                oldItem == newItem
        }

    }
}

7. PagingActivity

PagingExActivity.kt

class MyAdapter
    : PagingDataAdapter<Post2, MyViewHolder>(IMAGE_COMPARATOR) {


    class MyViewHolder(private val binding:ItemLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(post:Post2){
            Log.d("Adapter","bind 됨 ${post.id}")
            binding.userIdText.text = post.myUserId.toString()
            binding.idText.text = post.id.toString()
            binding.titleText.text = post.title
            binding.bodyText.text = post.body
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val binding = ItemLayoutBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return MyViewHolder(binding)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem = getItem(position)
        if(currentItem!=null){
            holder.bind(currentItem)
        }
    }

    companion object {
        private val IMAGE_COMPARATOR = object : DiffUtil.ItemCallback<Post2>() {
            override fun areItemsTheSame(oldItem: Post2, newItem: Post2) =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Post2, newItem: Post2) =
                oldItem == newItem
        }

    }
}
profile
Android Developer

0개의 댓글