본문 바로가기
Programando/Android

[Android/Kotlin] RecyclerView 사용하기

0. 종속성 추가

RecyclerView를 사용하기 위해서는 먼저 app 모듈의 build.gradle에 종속성을 추가해야 합니다.

dependencies {
    implementation "androidx.recyclerview:recyclerview:1.2.1"
    // For control over item selection of both touch and mouse driven selection
    implementation "androidx.recyclerview:recyclerview-selection:1.1.0"
}

 

1. 레이아웃 파일에 RecyclerView 추가

레이아웃 파일에 RecyclerView를 추가합니다. RecyclerView에는 widthheight 속성 외에도 꼭 추가해야 하는 속성들이 있습니다. 먼저, orientation 속성으로 목록을 세로 방향, 혹은 가로 방향으로 표시할 수 있도록 설정할 수 있습니다.

세로 방향으로 보기 위해서는 android:orientation="vertical", 가로 방향으로 보기 위해서는 android:orientation="horizontal"과 같이 속성을 추가합니다.

그 다음은 layoutManager 속성입니다. 이 속성은 리스트를 수평 혹은 수직으로 배치할 것인지(LinearLayoutManager), 그리드 화면으로 배치(2단, 3단 진열 등)할 것인지(GridLayoutManager), 아이템의 크기에 따라 높이나 너비가 불규칙한 그리드 화면으로 배치할 것인지(StaggeredGridLayoutManager)를 설정할 수 있습니다.

리스트를 수평 혹은 수직으로 배치하기 위해 app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"와 같이 속성을 추가합니다.

  • res/layout/activity_main.xml
    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

 

2. RecyclerView 아이템 레이아웃 추가

RecyclerView 아이템에 표시될 아이템 레이아웃을 생성합니다. 저는 사용자들의 이름과 나이가 담겨있는 리스트를 뿌려주기 위해 TextView 두 개로 이루어진 레이아웃을 작성했습니다.

  • res/layout/item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tvUserName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:layout_weight="1"
        tools:text="이름"/>

    <TextView
        android:id="@+id/tvUserAge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:layout_weight="1"
        tools:text="나이"/>

</LinearLayout>

 

3. Adapter 작성

AdapterRecyclerView.Adapter를 상속받아 구현하고, ViewHolderRecyclerView.ViewHolder를 상속받아 구현합니다.

먼저 ViewHolder를 구현합니다. ViewHolder는 우리가 만든 데이터를 실제 레이아웃의 데이터로 연결시키는 기능을 합니다.

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

    var datas = mutableListOf<User>()

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        val tvUserName: TextView = itemView.findViewById(R.id.tvUserName)
        val tvUserAge: TextView = itemView.findViewById(R.id.tvUserAge)

        // View와 데이터를 연결시키는 함수
        fun bind(item: User) {
            tvUserName.text = item.userName
            tvUserAge.text = item.userAge.toString()
        }

    }

    ...

}

 

그 다음에 구현할 Adapter에는 ViewHolder에 담길 데이터들, 데이터들과 레이아웃을 묶을 수 있게 레이아웃을 inflate할 수 있는 함수 등이 있어야 합니다. 해당 부분들은 RecyclerView.Adapter 제너릭 클래스에 존재하기 때문에 이를 상속받으면 됩니다.

  • RecyclerAdapter.kt
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {

    ...

    // 데이터와 레이아웃을 묶을 수 있게 레이아웃을 inflate하는 함수
    // viewGroup의 context를 사용하여 특정 화면에서 구현할 수 있도록 함
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context)
            .inflate(R.layout.item_user, parent, false))

    }

    // ViewHolder에서 데이터 묶는 함수가 실행되는 곳
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(datas[position])
    }

    override fun getItemCount() = datas.size

}
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {

    var datas = mutableListOf<User>()

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        val tvUserName: TextView = itemView.findViewById(R.id.tvUserName)
        val tvUserAge: TextView = itemView.findViewById(R.id.tvUserAge)

        fun bind(item: User) {
            tvUserName.text = item.userName
            tvUserAge.text = item.userAge.toString()
        }

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
    : RecyclerAdapter.ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context)
            .inflate(R.layout.item_user, parent, false))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(datas[position])
    }

    override fun getItemCount(): Int = datas.size
}

 

4. Adapter와 RecyclerView 연결

  • MainActivity.kt
class MainActivity : AppCompatActivity() {

    private val rvUserRecyclerView : RecyclerView by lazy {
        findViewById(R.id.rvUserRecyclerView)
    }

    private lateinit var RecyclerAdapter: RecyclerAdapter

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

        val userList: MutableList<User> = mutableListOf(
            User("테스트1", 20),
            User("테스트2", 25),
            User("테스트3", 42),
            User("테스트4", 66)
        ) // 임의로 생성한 데이터

        RecyclerAdapter = RecyclerAdapter(this)
        // Adapter 생성
        RecyclerAdapter.datas = userList
        // 테스트 데이터 리스트를 Adapter에 담고
        rvUserRecyclerView.adapter = RecyclerAdapter
        // 생성한 Adapter를 activity_main에 만들어둔 RecyclerView에 연결
    }
}

만약 리스트에 데이터를 추가하는 경우에는 RecyclerAdapter의 datas에 데이터를 추가한 후에 notifyDataSetChanged() 혹은

notifyItemInserted(position), notifyItemRangeChanged(positionStart, itemCount)를 통해 RecyclerView를 업데이트할 수 있습니다.

 

💡 RecyclerView에 데이터를 추가할 경우

✔️ notifyDataSetChanged()
    ㄴ 리스트의 크기와 아이템 모두 변경되는 경우에 사용합니다.
✔️ notifyItemInserted(position: Int)
    ㄴ 어느 특정 위치(position)에 아이템을 추가 할 때 사용합니다.
✔️ notifyItemRangeChanged(positionStart, itemCount)
    ㄴ 어느 특정한 위치(positionStart)부터 연속된 여러 개의 아이템을 추가할 때 사용합니다.
    ㄴ 추가할 아이템의 개수를 itemCount라는 변수로 지정해야 합니다.

 

5. 완성된 화면

개인적으로 데이터를 삭제/추가/수정함에 따라 RecyclerView가 업데이트되는 부분을 더 추가하였습니다.

 

그 외

완성 코드

https://github.com/na-ram/AOS_RecyclerView_Example.git  

 

자료 참조

https://todaycode.tistory.com/55

반응형