티스토리 뷰

728x90

 

 

RecyclerView

ListView와 동일하게 데이터 세트를 개별 아이템으로 구성하여 화면에 출력하는 ViewGroup 중 하나다.

여러 데이터를 스크롤할 수 있게 화면에 표시하는 위젯이다.

 

 

ListView와 다른점

ListView는 리스트가 갱신될 때마다 아이템 뷰를 새로 구성해야 한다는 단점이 있다.

반면에 RecyclerView는 이름에서 알 수 있듯이 개별 아이템을 재활용한다.

항목이 스크롤되어 화면에서 벗어나더라도 개별 뷰들을 제거하지 않고, 스크롤된 새로운 아이템의 뷰를 재사용하기 때문에 성능이 개선된다.

 

 

필요한 클래스

1. RecyclerView

   데이터 세트를 화면에 출력하는 ViewGroup

 

2. ViewHolder

   리스트의 개별 아이템은 ViewHolder 객체로 정의된다.

   RecyclerView에서 뷰 홀더를 뷰의 데이터에 바인딩해야 한다.

   뷰들을 재활용하기 위해 기존 View 객체를 가지고 있으며, 재활용한 View 객체에 데이터를 바인딩한다.

 

3. RecyclerView.Adapter

   뷰를 뷰의 데이터에 바인딩하는 역할을 한다.

   다른 ViewGroup과 다르게 RecyclerView에서는 Adapter 클래스를 반드시 구현해주어야 한다.

 

4. LayoutManager

   리스트의 개별 아이템을 정렬한다.

   직접 구현하거나 라이브러리를 사용한다.

   (LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager)

 

 

구현 단계

1. activity의 xml 파일에 recyclerView 추가

2. RecyclerView의 개별 아이템에 대한 xml 파일 생성

3. RecyclerView의 Adpater 구현

4. activity kotlin 코드 내에서 Adapter, LayoutManager 지정

 

 

 

1. activity의 xml 파일에 recyclerView 추가

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

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

 

 

 

2. RecyclerView의 개별 아이템에 대한 xml 파일 생성

recycler_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp">

        <TextView
            android:id="@+id/date_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:textSize="40sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/contents_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="50dp"
            android:textSize="24sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/date_text"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/posted_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:textSize="24sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/contents_text"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

하나의 아이템에 date_text, contents_text, posted_text 세 데이터가 들어갈 수 있도록 구현했다.

이때 layout_height는 wrap_content로 설정한다.

참고로 이 예제에서는 데이터 바인딩을 사용했다.

 

 

3. RecyclerView의 Adpater 구현

class TodoRecyclerViewAdapter(private var todoList: MutableList<Todo>) : RecyclerView.Adapter<TodoRecyclerViewAdapter.ViewHolder>() {

    class ViewHolder(val binding: RecyclerViewItemBinding) : RecyclerView.ViewHolder(binding.root)

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val currentItem = todoList[position]
        holder.binding.dateText.text = currentItem.date
        holder.binding.contentsText.text = currentItem.contents
        holder.binding.postedText.text = currentItem.posted
    }

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

어댑터는 RecyclerView.Adapter 클래스를 확장한다.

 

    class ViewHolder(val binding: RecyclerViewItemBinding) : RecyclerView.ViewHolder(binding.root)

어댑터 안에 ViewHolder 클래스도 정의해주었다. 이때는 RecyclerView.ViewHolder를 확장하고,

아까 만들어준 뷰 각각의 아이템 xml, RecyclerviewBinding 객체의 참조를 전달한다.

이 binding 변수를 통해서 ViewHolder와 뷰의 데이터를 바인딩 시킬 수 있다.

 

그리고 어댑터 안에 override 할 함수들은 아래와 같다.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder 
override fun onBindViewHolder(holder: ViewHolder, position: Int) 
override fun getItemCount(): Int

onCreateViewHolder(): 아이템 뷰를 위한 뷰홀더 객체를 생성하여 return

onBindViewHolder(): position에 해당하는 데이터를 뷰홀더의 아이템 뷰에 표시 (데이터를 바인딩)

getItemCount(): 전체 데이터의 개수 리턴

 

 

4. activity kotlin 코드 내에서 Adapter, LayoutManager 지정

        binding.recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        binding.recyclerView.adapter = TodoRecyclerViewAdapter(list)

아이템들을 수직적으로 배치할 것이기 대문에 LinearLayoutManager의 VERTICAL 속성을 사용했다.

 

 

 

이 예제에서는 리사이클러뷰에 대한 개념만 다루기 위해 list를 어댑터의 매개변수로 지정하는 방법을 사용했다.

list가 변하지 않는 데이터라면 이와 같은 방법을 사용하면 되지만,

list에 삽입, 삭제가 여러번 이루어진다면 이러한 방법은 비효율적일 것이다.

 

보통 리사이클러뷰는 mvvm 패턴과 같이 적용하여 list가 변경되면 리사이클러뷰의 뷰들도 변경되도록 구현한다.

 

 

 

참조

https://developer.android.com/guide/topics/ui/layout/recyclerview?hl=ko 

https://recipes4dev.tistory.com/154

728x90
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함