nueijeel

[Android] RecyclerView와 ViewHolder 본문

Android/개념

[Android] RecyclerView와 ViewHolder

nueijeel 2023. 6. 30. 15:48

 

RecyclerView

: 화면에 목록을 동적으로 표출하는 컨테이너

 

 

RecyclerView는 화면에 목록을 보여주는 뷰지만, Adapter와 ViewHolder가 없이는 목록을 표출 할 수 없다.

 

ViewHolder는 하나의 목록을 구성하는 뷰들의 객체를 보관하는 역할을 하고, Adapter는 뷰 홀더에 있는 뷰 객체에 표출할 데이터를 연결하는 역할을 한다.

 

목록이 표출되는 화면에서 스크롤을 하면 상단에 위치해있던 목록들은 하단에 항목들이 새로 나타남과 동시에 보이지 않게 된다. 이때 새로 표출되는 항목의 뷰를 일일이 생성하지 않고, 기존에 상단 목록을 표출할 때 사용했던 뷰 객체를 재사용하여 데이터만 새로 담아 사용할 수 있게 해주는 것이 ViewHolder이다.

 

ViewHolder를 사용하면 뷰 객체의 재사용성을 높여 성능을 최적화시킬 수 있다. 

 

 

RecyclerView를 통해 위와 같은 화면을 구성한다고 할 때, 목록 하나를 구성하는 뷰는 ImageView와 TextView이다. 

이 뷰 객체를 가지는 ViewHolder 클래스는 다음과 같이 구현된다.

 

class ViewHolderClass(rowBinding:RowBinding) : RecyclerView.ViewHolder(rowBinding.root){
    val textViewRow : TextView = rowBinding.textView1
    val imageViewRow : ImageView = rowBinding.imageView1
}

 

row.xml 파일에 개별 항목의 레이아웃을 구성해 놓고, 생성자로 받은 rowBinding 객체를 통해 레이아웃 내 각 뷰의 객체를 ViewHolderClass에서 생성한다.

여기서는 뷰 홀더에 연결된 데이터가 없이 틀만 형성된 상태이다. 

 

개별 항목의 이벤트 처리는 보통 ViewHolderClass 내에서 이루어진다.

 

 

이제 Adapter를 정의해 뷰 객체가 담긴 뷰 홀더에 데이터를 바인딩해 표시될 항목을 채워보자.

RecyclerView에서 Adapter를 만들 때는 ViewHolder와 관련된 세 개의 추상 메서드를 반드시 구현해야 한다.

 

1)  onCreateViewHolder()

ViewHolder를 새로 만들어야할 때 마다 호출되는 메서드로, 이를 통해 ViewHolder와 그에 연결된 View가 생성되고 초기화된다. 하지만 ViewHolder가 특정 데이터에 바인딩 되어있지 않기 때문에 여기서 뷰의 콘텐츠가 채워지진 않는다.

 

2) onBindViewHolder()

ViewHolder를 데이터와 연결할 때 호출되는 메서드로, ViewHolder의 객체에 특정 데이터를 담아 레이아웃을 완성한다. 메서드의 두 번째 매개변수 활용하여 목록 순서에 맞게 데이터를 바인딩할 수 있다.

 

3) getItemCount()

ViewHolder에 바인딩할 데이터의 전체 개수를 반환하는 메서드로 RecyclerView에 표시할 목록의 개수를 파악하는 용도이다.

 

class RecyclerAdapter(val textList: Array<String>, val imgList: IntArray) : RecyclerView.Adapter<ViewHolderClass>(){
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolderClass{
        val rowBinding = RowBinding.inflate(LayoutInflater.from(viewGroup.context),viewGroup,false)

        return ViewHolderClass(rowBinding)
    }

    override fun getItemCount(): Int{
        return textList.size
    }

    override fun onBindViewHolder(holder: ViewHolderClass, position:Int){
        holder.textViewRow.text = textList[position]
        holder.imageViewRow.setImageResource(imgList[position])
    }
}

 

RecyclerView.Adapter를 상속받아 어댑터 클래스를 구현했다. textList와 imgList라는 데이터를 ViewHolder에 담긴 뷰 객체에 담아 목록화면을 구성한다.

 

 

Adapter까지 만들었다면 RecyclerView에 목록을 출력하면 된다.

RecyclerView의 LayoutManager는 Adapter가 구성한 각 항목들을 어떻게 배치할지 결정해 출력한다.

 

recyclerView.run{
    adapter = RecyclerAdapter()
    layoutManager = LinearLayoutManager(this@MainActivity)
}

 

RecyclerView 의 adapter로 RecyclerAdapter 클래스의 객체를 담고, layoutManager를 LinearLayoutManager로 설정했다.

 

LinearLayoutManager는 orientation 속성을 지정해 항목을 가로나 세로 방향으로 배치한다. 이외에도 GridLayoutManager는 항목을 그리드 형식의 동일한 크기로 배치하고, StaggeredGridLayoutManager는 각 항목별 높이를 따라 항목 간 빈틈이 없게 배치한다.

 

 

차례로 LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager를 적용한 RecyclerView이다.

 

 

 

 

 

728x90

'Android > 개념' 카테고리의 다른 글

[Android] Activity 생명주기  (0) 2023.07.23
[Android] XML, JSON 데이터 가져오기  (0) 2023.07.18
[Android] Button과 뷰 이벤트  (0) 2023.06.26
[Android] ImageView  (0) 2023.06.20
[Android] ScrollView  (0) 2023.06.15