Android

[안드로이드]RecyclerView에 관하여

나맘임 2023. 5. 23. 15:39

RecyclerView란?

동적으로 레이아웃에 데이터를 표시하는 Container의 일종으로 ListView와 비슷하게 스크롤을 통해 목록을 표시하는 뷰이다.

단, ListView는 스크롤을 통해 데이터가 뷰에서 벗어나면 제거를 하지만, RecyclerView는 벗어난 뷰를 재사용하여 앱의 등답성을 개선하고 전력 소모를 줄이므로써 성능이 더 개선됐습니다.

 

주요 클래스

ViewGroup

RecyclerView는 데이터에 해당하는 뷰가 포함된 ViewGroup이므로, 다른 UI 요소를 추가할 때처럼 레이아웃에RecyclerView를 추가하면 됩니다.

 

ViewHolder

목록의 각 개별 요소를 뷰 홀더 객체로 정의합니다.

뷰 홀더를 처음 생성하게 되면 뷰 홀더에 연결된 데이터가 없기 때문에 RecyclerView가 뷰 홀더에 뷰의 데이터를 바인딩합니다.

ViewHolder를 정의할 땐 RecyclerView.ViewHolder를 확장하여 정의합니다.

Adapater

RecyclerView는 뷰를 요청한 다음, 어뎁터에서 메서드를 호출하여 뷰를 뷰의 데이터에 바인딩합니다.

어뎁터를 정의할 땐 RecyclerView.Adapter를 확장하여 정의합니다.

LayoutManager

레이아웃 관리자는 목록의 개별 요소를 정렬하는 역할을 합니다.

리스트를 가로로 배치하거나, 그디르 형태로 배치하는 등 다양한 레이아웃을 지원합니다.

 

구현 단계

1. 목록 또는 그리드 모양 결정

사용자가 원하는 대로 정의가 가능하나, 대개 RecyclerView 라이브러리의 표준 레이아웃 관리자 중 하나를 사용합니다.

2. 목록에 있는 각 요소의 모양과 동작 방식 설계

이 설계에 따라 ViewHolder 클래스를 확장합니다. ViewHolder은 목록 항목에 필요한 모든 기능을 제공합니다.

ViewHolder는 View의 래퍼이고 그 뷰는 RecyclerView로 관리됩니다.

3. 데이터를 ViewHolder 뷰와 연결하는 Adapter를 정의

 

레이아웃 계획

RecyclerView의 뷰들은 LayoutManager 클래스를 통해 정렬됩니다. 일반적인 레이아웃 상황을 처리하는 3가지 종류를 제공합니다.

1. LinearLayoutManager

뷰들을 1차원 목록으로 정렬합니다.

2. GridLayoutManager

뷰들을 2차원 그리드로 정렬합니다.

 

그리드를 세로로 정렬된 경우 GridLayoutManager는 각 행의 모든 요소를 동일한 너비와 높이로 만들려고 하지만 행마다 높이가 다를 수 있습니다.

 

그리드가 가로로 정렬된 경우 GridLayoutManager는 각 열의 모든 요소를 동일한 너비와 높이로 만들려고 열마다 너비가 다를 수 있습니다.

 

3. StaggeredGridLayoutManager

GridLayoutManager와 비슷하지만 행의 항목이 동일한 높이(세로 그리드일 경우)이거나 동이한 열의 항목이 동일한 너비(가로 그리드일 경우)일 필요가 없습니다. 결과적으로 행 또는 열의 항목이 서로 오프셋 상태가 될 수 있습니다.

 

Adapter 및 ViewHolder 구현

레이아웃을 결정했으면 Adapter 및 ViewHolder 를 구현해야 합니다. 이 두 클래스가 함께 작동하여 데이터 표시 방식을 정의합니다.

ViewHolder는 목록에 있는 개별 항목의 레이아웃을 포함하는 View의 래퍼이고, Adapter는 필요에 따라 ViewHolder 객체를 만들고 이러한 뷰에 데이터를 설정하기도 합니다.

추가로 뷰를 데이터에 연결하는 프로세스를 바인딩이라고 합니다.

 

어뎁터를 정의할 땐 다음 세 가지 키 메서드를 재정의해야 합니다.

onCreateViewHolder()

RecyclerView는 ViewHolder를 새로 만들어야 할 때마다 이 메서드를 호출합니다.

이 메서드는 ViewHolder 와 그에 연결된 View를 생성하고 초기화하지만 뷰의 콘텐츠를 채우진 않습니다.

이는 ViewHolder가 아직 특정 데이터에 바인딩된 상태가 아니기 때문입니다.

 

onBindViewHolder()

RecyclerView는 ViewHolder 를 데이터와 연결할 때 이 메서드를 호출합니다.

이 메서드는 적절한 데이터를 가져와서 그 데이터를 사용하여 뷰 홀더의 레이아웃을 채웁니다.

예를 들어, RecyclerView가 이름 목록을 표시하는 경우 메서드는 목록에서 적절한 이름을 찾아 뷰 홀더의 TextView 위젯을 채울 수 있습니다.

getItemCount()

RecyclerView는 데이터 세트 크기를 가져올 때 이 메서드를 호출합니다. 

예를 들어 주소록 앱에서는 총 주소 개수가 여기에 해당할 수 있습니다.

RecyclerView는 이 메서드를 사용하여, 항목을 추가로 표시할 수 없는 상황을 확인합니다.

class HomeListAdapter ()
    :RecyclerView.Adapter<HomeListAdapter.HomeListViewHolder>(){

    var itemList = mutableListOf<HomeListItem>()
    inner class HomeListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val titleView: TextView = itemView.findViewById<TextView>(R.id.itemDescTitle)
        val DataView : TextView = itemView.findViewById<TextView>(R.id.itemDescData)

        fun bind(position: Int){
            titleView.text= itemList[position].title
            DataView.text=itemList[position].data
            if(itemList[position].status){
                titleView.setTextColor(Color.parseColor("#74D6EA"))
                DataView.setTextColor(Color.parseColor("#74D6EA"))
            } else {
                titleView.setTextColor(Color.parseColor("#F06C83"))
                DataView.setTextColor(Color.parseColor("#F06C83"))
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeListViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_home_recycler_view,parent,false)
        return HomeListViewHolder(view)
    }

    override fun onBindViewHolder(holder: HomeListViewHolder, position: Int) {
        holder.bind(position)
    }

    override fun getItemCount(): Int {
        return itemList.count()
    }
    
    data class HomeListItem(val title:String, var data:String, var status:Boolean)

}