[Android/Kotlin] RecyclerView 활용법

최지원·2024년 1월 29일

[Android/Kotlin]

목록 보기
9/9

📌 RecyclerView란?

안드로이드 공식 문서에서 내리는 리사이클러뷰에 대한 정의 :

"리사이클러뷰는 화면에 대량의 데이터 목록을 표시하는 데 최적화된 위젯입니다. 리사이클러뷰를 사용하면 한 번에 화면에 표시되는 항목 수를 제한하면서도 사용자가 스크롤할 때 즉시 다음 또는 이전 항목을 로드하여 부드러운 스크롤링을 제공할 수 있습니다."

??? : 그런데.. 이거 읽어보면 ListView랑 비슷한거같은데 뭐가 다른거지?

리사이클러뷰와 리스트뷰의 차이

리사이클러뷰와 리스트뷰의 관계: 리사이클러뷰는 리스트뷰의 진화된 형태로 볼 수 있습니다. 리사이클러뷰는 리스트뷰의 단점을 보완하고, 추가적인 기능과 유연성을 제공합니다. 또한, 리사이클러뷰는 리스트뷰에 비해 더 높은 성능을 제공하며, 다양한 레이아웃 매니저를 통해 다양한 레이아웃을 구성할 수 있습니다.

리사이클러뷰의 채택: 안드로이드 개발 환경에서는 리사이클러뷰를 리스트뷰보다 권장합니다. 이는 리사이클러뷰가 더 효율적이고 유연하며, 성능이 뛰어나기 때문입니다. 또한, 리사이클러뷰는 애니메이션, 드래그 앤 드롭 등의 고급 기능을 쉽게 구현할 수 있습니다.

리사이클러뷰와 리스트뷰의 개념차이

  • 리스트뷰: 리스트뷰에서는 스크롤을 할 때마다 새로운 항목을 생성하고 이전의 항목은 화면 밖으로 사라집니다. 그러나 새로운 항목을 계속 생성하는 것은 비효율적이며, 메모리 사용량을 증가시킬 수 있습니다.
  • 리사이클러뷰: 리사이클러뷰는 화면에 보이는 항목만을 생성하고, 스크롤되면 화면에서 사라진 항목은 재활용됩니다. 즉, 화면에서 벗어난 항목은 위 그림과 같이 다시 사용될 수 있습니다. 이를 통해 메모리 사용량을 줄이고 성능을 향상시킬 수 있습니다.

리사이클러뷰의 장점

1. 성능 및 메모리 사용

리사이클러뷰는 뷰 홀더 패턴을 사용하여 항목을 재사용하므로 성능이 향상됩니다. 또한 화면에서 벗어난 항목은 다시 사용되는 뷰 홀더로 재활용되어 메모리 사용량이 최적화됩니다.

2. 유연성

리사이클러뷰는 다양한 레이아웃 매니저를 통해 다양한 레이아웃을 지원하며, 다양한 항목 유형을 표시하고 관리하는 데 유연성이 있습니다. 또한 리사이클러뷰는 항목 간의 애니메이션 및 드래그 앤 드롭과 같은 고급 기능도 제공합니다.

3. 어댑터의 역할

리사이클러뷰에서는 RecyclerView.Adapter 클래스를 상속받아 어댑터를 구현합니다. 이러한 어댑터는 더욱 유연하며, 항목 추가, 제거, 이동 등의 작업을 보다 쉽게 처리할 수 있습니다.

리사이클러뷰 구성요소

  • RecyclerView: 리사이클러뷰의 핵심 클래스로, 목록을 표시하고 스크롤 가능한 화면을 제공합니다. 리사이클러뷰는 항목의 재활용, 뷰 관리, 애니메이션 등을 담당합니다.

  • LayoutManager: 레이아웃 매니저는 리사이클러뷰에서 항목의 배치 방법을 결정합니다. 기본적으로 제공되는 레이아웃 매니저에는 LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager 등이 있습니다.

  • Adapter: 어댑터는 데이터와 뷰를 연결해주는 역할을 합니다. RecyclerView.Adapter 클래스를 상속받아 구현되며, onCreateViewHolder(), onBindViewHolder(), getItemCount() 등의 메서드를 오버라이드하여 구현합니다. onCreateViewHolder()는 뷰 홀더를 생성하고, onBindViewHolder()는 데이터를 뷰에 바인딩하며, getItemCount()는 표시할 항목의 개수를 반환합니다.

  • ViewHolder: 뷰 홀더는 RecyclerView의 각 항목에 대한 뷰와 데이터를 보유하는 역할을 합니다. RecyclerView.Adapter 클래스 내부에서 정의됩니다. 뷰 홀더 패턴을 통해 화면에서 보이지 않는 항목을 재활용하여 성능을 향상시킵니다.

RecyclerView 사용법

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.recyclerview.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var adapter: RecyclerViewAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val list = mutableListOf<RecyclerviewData>()
        list.add(RecyclerviewData("title1", "description1", "name1"))
        list.add(RecyclerviewData("title2", "description2", "name2"))
        list.add(RecyclerviewData("title3", "description3", "name3"))
        list.add(RecyclerviewData("title4", "description4", "name4"))
        list.add(RecyclerviewData("title5", "description5", "name5"))

        adapter = RecyclerViewAdapter()
        adapter.setList(list)
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.adapter = adapter

    }
}

어댑터 초기화와 어댑터 layoutManager를 설정하는 부분입니다.
어댑터의 setList메서드를 통해 어댑터로 데이터를 전달합니다.

RecyclerviewData.kt

data class RecyclerviewData(
    val title: String,
    val description: String,
    val name: String
)

어댑터에 전달할 데이터를 정리한 데이터클래스 입니다.

RecyclerViewAdapter.kt

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.recyclerview.databinding.ItemRecyclerBinding


class RecyclerViewAdapter: RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {

    private var itemList: MutableList<RecyclerviewData> = mutableListOf()

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

    override fun getItemCount(): Int = itemList.size

    override fun onBindViewHolder(holder: RecyclerViewAdapter.ViewHolder, position: Int) {
        val current = itemList[position]
        holder.bind(current)
    }

    fun setList(list: MutableList<RecyclerviewData>){
        this.itemList = list
        notifyDataSetChanged()
    }

    inner class ViewHolder(private val binding: ItemRecyclerBinding): RecyclerView.ViewHolder(binding.root){
        fun bind(item: RecyclerviewData){
            binding.title.text = item.title
            binding.description.text = item.description
            binding.name.text = item.name
        }
    }
}

앞서 설명드린 어댑터의 구성 요소들이 포함된 부분입니다. setList 메서드를 통해 데이터를 받고 itemList를 가공하여 RecyclerView에 뿌립니다.

item_recycler.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:padding="10dp"
    android:background="@drawable/rectangle_black"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toTopOf="@id/description"
        app:layout_constraintVertical_chainStyle="packed"
        android:layout_marginBottom="10dp"
        android:textStyle="bold"
        android:textSize="20dp"
        android:textColor="@color/black"/>
    <TextView
        android:id="@+id/description"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title"
        android:textStyle="bold"
        android:textSize="20dp"
        android:textColor="@color/black"/>
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:textStyle="bold"
        android:textSize="20dp"
        android:textColor="@color/black"/>

</androidx.constraintlayout.widget.ConstraintLayout>

뷰홀더를 구성하는 xml파일입니다. 이 뷰홀더가 RecyclerView의 각 데이터에 구성됩니다.

결과화면

profile
안드로이드, 플러터 주니어입니다

0개의 댓글