728x90
RecyclerView with multiple item types in Kotlin이란?
개발을 하다보면 여러 개의 Recycler View를 만들게 되어 프로젝트 구조가 복잡해지기 마련이다. 예를 들면 하나의 Recycler View에 여러 타입의 뷰를 띄워야 하는 경우도 있습니다. 예를 들면, 네이버 카페 어플에서 글을 본다고 할 때, 사진+제목, 제목, 광고와 같은 타입으로 아이템이 나눠질 수 있다.
하나의 View에는 하나의 DataItem밖에 들어가야하지 않을까?
나도 처음에는 그렇게 생각하였지만 공부를 하면서 그렇게 하지 않아도 된다는 점을 발견하였다.
여러가지 방법이 있다.
하지만 이번 포스팅에서는 "Sealed Class를 활용해서 ViewHolder와 Item 묶어내는 방법"으로 Mutiple item types를 구현했다.
아래는 프로젝트 코드이다.
MovieData
val movies : MutableList<MovieItems> = mutableListOf<MovieItems>().apply {
add(MovieItems.TextMovie(1, "이미지 없는 영화1"))
add(MovieItems.ImageMovie(2, R.drawable.post1, "스마일"))
add(MovieItems.TextMovie(3, "이미지 없는 영화2"))
add(MovieItems.ImageMovie(4, R.drawable.post2, "노량"))
add(MovieItems.TextMovie(5, "이미지 없는 영화3"))
add(MovieItems.ImageMovie(6, R.drawable.post3, "범죄도시3"))
add(MovieItems.TextMovie(7, "이미지 없는 영화4"))
add(MovieItems.ImageMovie(8, R.drawable.post4, "서울의 봄"))
add(MovieItems.TextMovie(9, "이미지 없는 영화5"))
add(MovieItems.ImageMovie(10, R.drawable.post5, "실미도"))
add(MovieItems.TextMovie(11, "이미지 없는 영화6"))
add(MovieItems.ImageMovie(12, R.drawable.post6, "파묘"))
add(MovieItems.TextMovie(13, "이미지 없는 영화7"))
}
sealed Class MovieItems
sealed class MovieItems {
data class ImageMovie(
val id: Int, val image: Int, val title: String
) : MovieItems()
data class TextMovie(
val id: Int, val title: String
) : MovieItems()
}
ImageViewHolder
class ImageViewHolder(
private val binding: ItemImageMovieBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: MovieItems.ImageMovie) = with(binding){
previewImageView.setImageResource(item.image)
movieTitle.text = item.title
}
}
TitleViewHolder
class TitleViewHolder(
private val binding: ItemTitleMovieBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: MovieItems.TextMovie) = with(binding){
MovieTitleView.text = item.title
}
}
MovieAdapter
class MovieAdapter : ListAdapter<MovieItems, RecyclerView.ViewHolder>(diffCallback) {
override fun getItemViewType(position: Int): Int {
return when (currentList[position]) {
is MovieItems.ImageMovie -> ITEM_IMAGE
is MovieItems.TextMovie -> ITEM_TITLE
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
Log.d("RecyclerView", "onCreateViewHolder")
val layoutInflater = LayoutInflater.from(parent.context)
return when (viewType) {
ITEM_IMAGE -> {
val binding = ItemImageMovieBinding.inflate(layoutInflater, parent, false)
ImageViewHolder(binding)
}
else -> {
val binding = ItemTitleMovieBinding.inflate(layoutInflater, parent, false)
TitleViewHolder(binding)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
Log.d("RecyclerView", "onBindViewHolder $position")
when (holder) {
is ImageViewHolder -> {
holder.bind(currentList[position] as MovieItems.ImageMovie)
}
is TitleViewHolder -> {
holder.bind(currentList[position] as MovieItems.TextMovie)
}
}
}
companion object {
private val diffCallback = object : DiffUtil.ItemCallback<MovieItems>() {
override fun areItemsTheSame(oldItem: MovieItems, newItem: MovieItems): Boolean {
return oldItem === newItem
}
override fun areContentsTheSame(oldItem: MovieItems, newItem: MovieItems): Boolean {
return oldItem == newItem
}
}
const val ITEM_IMAGE = 0
const val ITEM_TITLE = 1
}
}
실행화면
프로젝트 링크
https://github.com/ois0886/Android_Side_Projects/tree/main/RecyclerViewStudy
참고
https://rccode.tistory.com/285
https://developer-munny.tistory.com/2
https://medium.com/@ruut_j/a-recyclerview-with-multiple-item-types-in-kotlin-80e1e36d93e6
728x90
'Android > Study' 카테고리의 다른 글
[Android] RecyclerView에서 onCreateViewHolder와 onBindViewHolder의 차이 (0) | 2024.06.09 |
---|---|
[Android] DIP에 대해서 공부하자 (0) | 2024.06.09 |
[Android] SharedPreferences & 자동 로그인 구현 (0) | 2024.06.01 |
[Android] runOnUiThread()에 대해서 공부해보자 (0) | 2024.06.01 |
[Android] onNewIntent()에 대해서 알아보자. (0) | 2024.04.20 |