티스토리 뷰

RecyclerView

여러가지 항목을 나열하는 목록 화면을 만들 때 사용한다.

+ 리스트뷰는 androidx 라이브러리에서 리사이클러 뷰를 제공하기 시작하면서부터 잘 사용되지 않는다.

 


RecyclerView의 구성요소

  • ViewHolder: 항목에 필요한 뷰 객체를 가진다. 필수
  • Adapter: 항목을 구성한다. 필수
  • LayoutManager: 항목을 배치한다. 필수
  • ItemDecoration: 항목을 꾸민다.
뷰 홀더각 항목을 구성하는 뷰 객체를 가지며
어댑터뷰 홀더에 있는 뷰 객체에 적절한 데이터를 대입해 항목을 완성한다.
레이아웃 매니저어댑터가 만든 항목들을 어떻게 배치할지 결정하여 리사이클러 뷰에 출력한다.

 


RecyclerView 사용

1. 리사이클러 뷰 선언

 

  • 그래들 파일의 dependencies 항목에 다음처럼 선언
implementation 'androidx.recyclerview:recyclerview:1.1.0'

 

+ 안드로이드 스튜디오 4.1 버전부터 머티리얼 디자인 라이브러리를 자동으로 추가해주고 있어 그래들 파일에 recyclerview를 등록하지 않아도 앱에서 이용하는데 문제가 없을 수 있다.

 

2. 레이아웃 XML 파일에 리사이클러 뷰 등록

 

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

 

목록에 표시할 항목을 디자인한 레이아웃 XML 파일도 필요하다

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1.5"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:maxLines="1"/>

    </LinearLayout>

</LinearLayout>

 

3. 뷰 홀더 준비

 

  • 각 항목에 해당하는 뷰 객체를 가지는 뷰 홀더는 RecyclerView.ViewHolder를 상속받아 작성한다.
  • 원래는 뷰 홀더에 항목들의 뷰 객체를 선언하고 findViewById로 가져와야 하지만 뷰 바인딩 기법을 이용하면 뷰 홀더는 항목 레이아웃 XML 파일에 해당하는 바인딩 객체만 가지고 있으면 된다. 이 바인딩 객체에 항목을 구성하는 뷰가 자동으로 선언되었으므로 짧은 코드로 작성할 수 있다.
class ToDoViewHolder(val binding: ItemTodoBinding): RecyclerView.ViewHolder(binding.root)

 

4. 어댑터 준비

 

  • 어댑터는 뷰 홀더의 뷰에 데이터를 출력해 각 항목을 만들어 주는 역할을 한다.
  • 리사이클러 뷰를 위한 어댑터는 RecyclerView.Adapter를 상속받아 작성한다.
  • 아래 코드의 ToDoAdapter 생성자의 매개변수는 액티비티에서 전달받는 항목 구성용 데이터이다.

어댑터에 재정의해야 하는 함수

  • getItemCount(): 항목 개수를 판단하려고 자동으로 호출된다.
  • onCreateViewHolder(): 항목의 뷰를 가지는 뷰 홀더를 준비하려고 자동으로 호출된다.
  • onBindViewHolder(): 뷰 홀더의 뷰에 데이터를 출력하려고 자동으로 호출된다.
getItemCount() 함수는 자동 호출되어 항목의 개수를 판단한다. 이 함수가 반환한 숫자만큼 onBindViewHolder() 함수가 호출되어 항목을 만든다. 만약 이 함수가 0을 반환하면 화면에는 아무것도 나오지 않는다.

onCreateViewHolder() 함수에서 반환한 뷰 홀더 객체는 자동으로 onBindViewHolder() 함수의 매개변수로 전달된다.

 

class ToDoAdapter(val myToDoSet: List<MyToDoList>
                  ): RecyclerView.Adapter<ToDoAdapter.ToDoViewHolder>() {
    class ToDoViewHolder(val binding: ItemTodoBinding): RecyclerView.ViewHolder(binding.root)

    override fun getItemCount(): Int = myToDoSet.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ToDoViewHolder =
        ToDoViewHolder(ItemTodoBinding.inflate(LayoutInflater.from(parent.context),
            parent, false))

    override fun onBindViewHolder(holder: ToDoViewHolder, position: Int) {
        val binding = (holder as ToDoViewHolder).binding
        binding.title.text = myToDoSet[position].title
        binding.content.text = myToDoSet[position].content
    }

}

 

5. 리사이클러 뷰 출력

 

리사이클러 뷰에 어댑터와 레이아웃 매니저를 등록하여 화면에 출력한다.

 

val recyclerView = binding.todoRecyclerView
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = ToDoAdapter(myToDoSet)

 

+ 항목을 동적으로 추가.제거

 

  • 항목을 구성하는 데이터에 새로운 데이터를 추가하거나 제거한 후에는 어댑터의 notifyDataSetChanged() 함수를 호출하면 된다.
val binding = ActivityToDoBinding.inflate(layoutInflater)
myToDoSet.add(MyToDoList(title, content))
binding.todoRecyclerView.adapter?.notifyDataSetChanged()

 


참고

깡샘의 안드로이드 앱 프로그래밍 with 코틀린