본문 바로가기
📱 Android

[Android] RecyclerView - MultiViewHolder(2)

by 콩드로이드 2022. 7. 13.

2021.05.15 - [Android] - [Android] RecyclerView (1) - Multi ViewHolder

 

[Android] RecyclerView (1) - Multi ViewHolder

안녕하세요 :) 오늘은 RecyclerView를 사용해보겠습니다 굉장히 자주 쓰이는 부분이기에 저 또한 더 자세히 알아두고자 정리해보려 합니다. (사용 빈도는 높지만 프로젝트를 처음부터 구현하지 않

kong-droid.com

 

기존 포스팅이 존재하지만, 기존 포스팅에선 같은 모델에서 type에 따라 나누는 방식을 사용했지만

보통 RecyclerView를 사용할 때 다양한 Model을 사용하기 때문에

ViewHolder별로 다른 DTO를 MultiViewHolder로 보이는 방식을 사용해 보겠습니다 


코드를 보기 전에 이번 포스팅에서 사용할 Sealed Class에 대해 알아보자면, 

 

Sealed Class

 

abstract class로 자신을 상속받는 하위클래스들을 가질 수 있습니다.

상속을 보다 효율적으로 관리하고, 제한된 클래스의 계층구조를 나타내고 컴파일 시 SubClass들을 알 수 있습니다

 

Enum Class와 비슷한 형태이지만,  Enum class는 아래와 같은 제약사항이 있습니다

📍 Enum의 제약사항
     • Single Instance
     • 서브 클래스 생성 불가 
     • 생성 후 속성값 변경 불가 

하지만, Sealed Class는 위의 제약사항들에 영향을 받지 않습니다 


📌 MultipleViewHolder

위와 같이 하나의 RecyclerView를 Top, Items로 사용한다고 가정하겠습니다

 

1. DTO 생성하기 

• sealed class를 사용해서 각 ViewHolder에서 사용될 DTO를 정의합니다 

• 각 TYPE을 구분하기 위해 ZERO, ONE을 정의합니다 

sealed class DTO {
    data class Top(val main: String) : DTO()
    data class Item(val img: Int, val title: String, val msg: String) : DTO()
}

object TYPE{
     const val ZERO = 0
     const val ONE = 1
}

 

 

2.  각각 ViewHolder 생성하기

• 각 ViewHolder별로 생성될 UI와 Data를 연결합니다 (with. DataBinding)

class MainTop(val binding: MainTopBinding) : RecyclerView.ViewHolder(binding.root) {
    fun bind(item: DTO.Top) {
        binding.tvTxt.text = item.main
    }
}
class MainSecond(val binding: MainSecondBinding) : RecyclerView.ViewHolder(binding.root) {
    fun bind(item: DTO.Item) = with(binding) {
        tvTxt.text = item.title
        imgCon.background = ContextCompat.getDrawable(root.context, item.img)
        tvComment.text = item.msg
    }
}

 

3.  RecyclerView Adapter 생성

1) create

viewType별로 각각의 Holder를 생성합니다 

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    when (viewType) {
        TYPE.ZERO -> {
            return MainTop(
                MainTopBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
            )
        }
        TYPE.ONE -> {
            return MainSecond(
                MainSecondBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
            )
        }
        else -> {
            throw Exception("onCreateViewHolder Error")
        }
    }
}

 

2) bind

• ViewHolder에 데이터를 결합시킵니다

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    when (holder) {
        is MainTop -> {
            holder.bind(itemList[position] as DTO.Top)
        }
        is MainSecond -> {
            holder.bind(itemList[position] as DTO.Item)
        }
    }
}

 

3) addItem

• ViewController로부터 데이터를 받는 부분입니다 

fun addTops(item: DTO.Top) {
    this.itemList.add(item)
}

@SuppressLint("NotifyDataSetChanged")
fun addItems(item: List<DTO.Item>) {
    this.itemList.addAll(item)
    notifyDataSetChanged()
}

 

 

4.  Activity에서 Recycler 생성 및 어댑터 연결

 

• Adapter를 생성하고 3에서 생성한 함수를 통해 데이터를 전달합니다

private fun initView() = with(binding) {
    recyclerView.adapter = MainAdapter()
    (recyclerView.adapter as MainAdapter).addTops(DTO.Top("👍🏻 List of hobbies"))

    val items = arrayOf(
        DTO.Item(R.drawable.ic_and, "Android", "Android Develop"),
        DTO.Item(R.drawable.ic_music, "Music", "K-Pop"),
        DTO.Item(R.drawable.ic_swim, "Swim", "Enjoy Summer")
    )
    (recyclerView.adapter as MainAdapter).addItems(items.toList())
}

 

결과화면

 

포스팅에선 Activity에서 데이터를 직접 생성했지만, API와 통신할때도 마찬가지고 위와 같은 구조를 사용하시면 됩니다 

RecyclerView를 사용하다보면 거진 Multi ViewHolder를 사용할텐데 sealed class를 사용하니 한결 구조화된 느낌이 들었습니다 

전체 코드는 아래 GitHub에 있습니다 😀

https://github.com/eunie9498/MultipleViewHolder

 

GitHub - eunie9498/MultipleViewHolder: MultipleViewHolder

MultipleViewHolder . Contribute to eunie9498/MultipleViewHolder development by creating an account on GitHub.

github.com


궁금하신 점이나 의견이 있으시면 댓글 부탁드립니다 감사합니다 😊

'📱 Android' 카테고리의 다른 글

[Android] Custom Spinner  (0) 2022.08.09
[Android] Custom Rating Bar  (0) 2022.08.04
[Android] Fragment LifeCycle  (0) 2022.07.06
[Android] 4대 Component  (0) 2022.07.05
[Android] Activity LifeCycle 🧐  (0) 2022.07.03