안드로이드의 RecyclerView는 대량의 데이터를 효율적으로 표시하기 위해 설계된 강력한 UI 컴포넌트로써, RecyclerView는 성능과 유연성 면에서 이전의 ListView를 대체하기 위해 도입되었다.
리사이클러뷰 또한 리스트뷰와 같은 구조를 같는다. 리사이클러뷰를 사용할 액티비티에서 리사이클러뷰 Adapter로 리스트형태의 데이터를 넘겨주고 Adapter에서 리스트형태의 데이터를 이용하여 아이템을 구성한다.
ViewHolder는 리사이클러뷰에서 개별 아이템 뷰를 보유하는 클래스로 ViewHolder는 RecyclerView.Adapter의 하위 클래스에서 생성되어 관리한다. 뷰 홀더의 주요 역할은 레이아웃을 미리 인플레이트하고 재사용할 수 있도록 한다. 리사이클러뷰는 뷰 홀더 패턴을 강제적으로 사용함으로써 성능적인 부분이 뛰어나기 때문에, 뷰홀더는 리스트뷰보다 리사이클러뷰를 사용하는 이유이기도 하다.
구현하는 방법 또는 구현하는 순서 같은 경우 여러가지가 있겠지만 내가 가장 익숙하게 사용했던 방법을 순서대로 정리해 보자.
data class ListViewModel(
val title : String = "",
val content : String = ""
)
class RecyclerViewPracticeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_recycler_view_practice)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val items = mutableListOf<ListViewModel>()
items.add(ListViewModel("나이키","조던"))
items.add(ListViewModel("아디다스","슈퍼스타"))
items.add(ListViewModel("뉴발란스","574"))
items.add(ListViewModel("반스","어센틱"))
val rv : RecyclerView = findViewById(R.id.rv)
rv.adapter = RVAdapter(items,this)
rv.layoutManager = LinearLayoutManager(this)
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:text="title"
android:textSize="20sp"
android:id="@+id/itemTitle"
android:layout_width="wrap_content"
android:layout_height="60dp"/>
<TextView
android:text="content"
android:layout_marginLeft="10dp"
android:textSize="15sp"
android:id="@+id/itemContent"
android:layout_width="wrap_content"
android:layout_height="60dp"/>
</LinearLayout>
class RVAdapter(val items : MutableList<ListViewModel>,context : Context) : RecyclerView.Adapter<RVAdapter.ViewHolder>(){
private val context : Context = context
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RVAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.rv_item,parent,false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: RVAdapter.ViewHolder, position: Int) {
holder.bindItems(items[position])
}
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(item:ListViewModel){
val title = itemView.findViewById<TextView>(R.id.itemTitle)
val content = itemView.findViewById<TextView>(R.id.itemContent)
itemView.setOnClickListener{
Toast.makeText(context,"${item.title.toString()} : ${item.content.toString()}",Toast.LENGTH_LONG).show()
}
title.text = item.title
content.text = item.content
}
}
}
리사이클러뷰도 이런 식으로 아이템 클릭에 대한 이벤트 처리를 할수 있다.
두개 다 사용해본 결과 기본적인 구현은 리스트뷰가 훨씬 구현하기 편리하지만, 리사이클러뷰가 장점이 훨씬 많다는 생각이 들었다. 다른 장점도 많지만 가장 큰 장점은 뷰홀더를 사용함으로 인한 성능적인 부분이라고 생각한다. 리스트뷰 같은 경우는 뷰홀더 패턴이 강제적이지 않지만, 리사이클러 뷰 같은 경우 뷰홀더 패턴의 강제적인 사용으로 뷰를 재사용하여 화면에서 벗어나는 뷰는 재사용 큐에 저장되고, 새로 스크롤할 때 기존 뷰를 재사용하여 성능을 크게 향상시킨다는 점인것 같다.