질문 정리

첫 안드로이드의 벽, RecyclerView 사용 방법

five2week 2023. 5. 30. 10:32

안드로이드 리싸이클러뷰(RecyclerView)란?

안드로이드 리싸이클러뷰(RecyclerView)는 안드로이드 앱에서 리스트 형태의 데이터를 효율적으로 표시하고 관리하기 위한 위젯입니다. 리싸이클러뷰는 이전에 사용되던 리스트뷰(ListView)보다 더 강력하고 유연한 기능을 제공합니다.리싸이클러뷰는 다음과 같은 주요 특징을 가지고 있습니다:

1. 재활용(View Recycling): 리싸이클러뷰는 화면에 보여지는 항목만을 생성하고 재활용하여 메모리 사용량을 최적화합니다. 스크롤 시에도 새로운 항목을 생성하는 대신 기존에 보이지 않던 항목을 재활용하여 데이터를 업데이트합니다.

2. 레이아웃 매니저(Layout Manager): 리싸이클러뷰는 레이아웃 매니저를 사용하여 항목의 배치 방식을 결정합니다. 수직 또는 수평으로 스크롤하는 리스트, 그리드 형태의 격자, 뷰페이저와 같은 페이징된 리스트 등 다양한 레이아웃 형식을 지원합니다.

3. 어댑터(Adapter): 리싸이클러뷰는 어댑터를 통해 데이터를 관리하고 항목의 뷰를 생성합니다. 어댑터는 데이터 소스와 리싸이클러뷰 간의 중개자 역할을 수행하며, 필요한 경우 항목의 뷰를 동적으로 업데이트할 수 있습니다.

4. 애니메이션 및 사용자 정의: 리싸이클러뷰는 항목 추가, 제거, 업데이트 등의 작업에 대한 애니메이션을 지원하며, 필요에 따라 사용자 정의할 수 있습니다. 또한, 항목의 터치 이벤트에 대한 처리도 쉽게 구현할 수 있습니다.

리싸이클러뷰는 안드로이드 개발에서 많이 사용되는 컴포넌트로, 대량의 데이터를 효율적으로 처리하고 동적인 UI를 구현하는 데 유용합니다.

 

리싸이클러뷰(RecyclerView)와 리스트뷰(ListView)

  RecyclerView ListView
ViewHolder 뷰홀더 패턴이 강제됨 뷰홀더 패턴을 사용하지 않아도 됨
Item Layout Linear, Grid, Staggered Gird가 지원됨 세로 방향만 지원
Item Animation 아이템 애니메이션을 처리하는 클래스 존재 아이템이 추가. 삭제될 때 적용할 수 있는 애니메이션이 없음
Adapter 커스텀 어댑터 필요 안드로이드에서 제공하는 어댑터를 사용하거나 BaseAdapter를 상속받아서 커스텀해서 사용
Decoration ItemDecoration 객체를 사용 android:divider 속성을 사용
Click Detection 개별 터치 이벤트를 관리하지만 클릭 처리기능이 내장되어 있지 않음 onItemClickLisner 인터페이스가 존재

 

뷰홀더 패턴(View Holder Pattern)

뷰홀더 패턴(View Holder Pattern)은 리스트뷰나 리싸이클러뷰와 같은 AdapterView에서 사용되는 패턴입니다. 이 패턴은 리스트뷰나 리싸이클러뷰에서 발생하는 뷰의 재사용 문제를 해결하기 위해 도입되었습니다. 뷰홀더 패턴을 사용하면 뷰의 생성 및 검색 작업을 최소화하여 성능을 향상시킬 수 있습니다.
일반적으로 리스트뷰나 리싸이클러뷰에서는 데이터를 바탕으로 각 항목에 해당하는 뷰를 생성합니다. 그러나 항목이 많을 경우 매번 뷰를 새로 생성하는 것은 비효율적입니다. 뷰홀더 패턴은 이러한 문제를 해결하기 위해 사용되는데, 각 항목의 뷰를 한 번 생성하고 재활용하기 위해 뷰홀더(ViewHolder)라는 객체를 사용합니다.
뷰홀더는 항목에 해당하는 뷰들을 참조하고 보관하는 역할을 수행합니다. 뷰홀더 객체는 onCreateViewHolder() 메서드에서 항목의 뷰를 생성할 때 함께 생성되며, onBindViewHolder() 메서드에서는 뷰홀더에 저장된 뷰들을 바탕으로 데이터를 바인딩합니다. 이렇게 뷰홀더 패턴을 사용하면 매번 findViewById()와 같은 뷰 검색 작업을 수행하지 않고도 뷰를 재활용하여 성능을 향상시킬 수 있습니다.
리싸이클러뷰는 뷰홀더 패턴을 기본적으로 지원하며, onCreateViewHolder() 메서드에서 ViewHolder를 생성하고, onBindViewHolder() 메서드에서 데이터를 바인딩합니다. 리스트뷰도 ViewHolder를 사용할 수 있지만, 리싸이클러뷰보다는 덜 유연하고 성능 면에서는 약간 떨어질 수 있습니다.

리싸이클러뷰(RecyclerView) 구현에 필수적인 요소

1. 레이아웃 파일

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

리싸이클러뷰가 존재했으면 하는 위치에 위의 코드 추가합니다. 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:padding="10dp" />
</LinearLayout>

리싸이클러뷰에 들어갈 아이템 코드는 위와 같습니다.

 

2. 어댑터 클래스

class MyAdapter(private val data: List<String>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = data[position]
        holder.textView.text = item
    }

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

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val textView: TextView = itemView.findViewById(R.id.textView)
    }
}
  • onCreateViewHolder(): 새로운 항목 뷰를 생성하는 메서드입니다. 이 메서드는 RecyclerView.ViewHolder 객체를 생성하고 반환합니다. 뷰를 생성하기 위해 LayoutInflater를 사용하여 item_layout.xml 레이아웃 파일을 인플레이트합니다. 이 때, parent는 리싸이클러뷰를 감싸는 부모 뷰그룹이며, false로 설정하여 부모 뷰그룹에 바로 붙지 않고 반환된 뷰를 ViewHolder에 넣은 후에 추가합니다.
  • onBindViewHolder(): 재활용되는 뷰홀더 객체에 데이터를 바인딩하는 메서드입니다. 해당 위치(position)에 있는 데이터를 가져와서 뷰홀더의 텍스트뷰에 설정합니다. 이 메서드는 리싸이클러뷰가 새로운 데이터를 표시해야 할 때마다 호출됩니다.
  • getItemCount(): 전체 데이터 항목의 수를 반환하는 메서드입니다. 리싸이클러뷰에 표시될 항목의 개수를 결정하는데 사용됩니다.
  • ViewHolder 내부 클래스: 뷰홀더 클래스입니다. 뷰홀더는 RecyclerView.ViewHolder를 상속받아 구현되며, 항목에 대한 뷰들을 참조하는 역할을 합니다. 위의 코드에서는 TextView를 참조하는 textView 변수를 정의하고, ViewHolder 생성자에서 해당 뷰를 찾아 할당합니다.

이렇게 구현된 MyAdapter 클래스는 데이터 목록을 받아와서 리싸이클러뷰에 표시하는 역할을 수행합니다. onCreateViewHolder() 메서드에서 뷰를 생성하고, onBindViewHolder() 메서드에서 데이터를 바인딩하여 리싸이클러뷰에 표시됩니다. getItemCount() 메서드는 데이터 항목의 수를 반환하여 리싸이클러뷰가 몇 개의 항목을 표시해야 하는지 결정합니다.

 

아래는 데이터바인딩을 사용한 코드입니다.

class MyAdapter(private val data: List<String>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = data[position]
        holder.bind(item)
    }

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

    inner class ViewHolder(private val binding: ItemLayoutBinding) : RecyclerView.ViewHolder(binding.root) {

        fun bind(item: String) {
            binding.textView.text = item
        }
    }
}

 

ItemLayoutBinding 부분의 이름은 리싸이클러뷰에서 사용하는 아이템의 이름에 따라서 달라지는 부분이므로, 사용하는 아이템의 이름을 확인해야합니다.

 

3. 액티비티 클래스

class MainActivity : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: MyAdapter
    private lateinit var dataList: MutableList<String>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        recyclerView = findViewById(R.id.recyclerView)
        recyclerView.layoutManager = LinearLayoutManager(this)

        dataList = mutableListOf()
        dataList.add("New Data 1")
	dataList.add("New Data 2")
	dataList.add("New Data 3")

        adapter = MyAdapter(dataList)
        recyclerView.adapter = adapter
    }
}
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var adapter: MyAdapter
    private lateinit var dataList: MutableList<String>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        dataList = mutableListOf()
        
        dataList.add("New Data 1")
	dataList.add("New Data 2")
	dataList.add("New Data 3")

        adapter = MyAdapter(dataList)
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.adapter = adapter
    }
}

리싸이클러뷰를 화면에 나타내려면 어댑터와 레이아웃 매니저를 연결해야합니다. 레이아웃 매니저는 리싸이클러뷰가 아이템을 화면에 표시할 때, 아이템 뷰들이 리싸이클러뷰 내부에서 배치되는 형태를 관리하는 요소입니다. 종류는 3가지로, LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager가 제공됩니다. 

 

다음에는 DividerItemDecoration, itemClickListener, ListAdapter 등 리싸이클러뷰를 사용하는데 필수적인 부분이 아닌 부가적인 부분을 정리하도록 하겠습니다.