본문 바로가기
Kotlin 공부 노트

리사이클러뷰(RecyclerView)만들어보기

by 지게요 2021. 12. 24.
728x90
반응형

# 리사이클러뷰(RecyclerView)

리사이클러뷰는 이름과 같이 재활용 개념이 들어간 뷰이고 가장 위의 아이템을 삭제하지 않고 가장 아래의 아이템 쪽으로 객체를 이동시켜 재사용을 할 수 있도록 고안되었다.

리사이클러뷰는 그리드 뷰, 리스트뷰와 비슷한 구조이지만 그리드, 리스트보다 더 유연하고 성능이 더 개선된 위젯이다.

 

※ 리스트뷰보다 좋은 점

출처 : https://www.crocus.co.kr/1704

사진을 보면 100개의 아이템이 있다면 100개의 아이템을 생성해야 하는 리스트뷰와 달리 리사이클러 뷰는 13개의 아이템으로 객체를 재활용하며 계속 사용할 수 있는 장점이 있다. 

리스스뷰와 리사이클러뷰의 차이점은 아래와 같다

리사이클러뷰(RecyclerView) 리스트뷰(Listview)
가로,세로,Grid 형식 모두 지원 세로 방향만 지원
ViewHolder 패턴을 이용 ViewHolder 패턴을 이용하지 않는다
아이템 애니메이션 처리 클래스가 있다 아이템 애니메이션 처리 클래스가 없다
Adapter는 데이터 제공을 위해 직접 구현 다양한 소스에 대한 Adapter 존재
개별 터치 이벤트를 관리하지만 클릭 처리 기능이 내장되어 있지 않다. 목록의 개별 항목에 대한 클릭 이벤트에 바인딩하기 위한 인터페이스가 존재한다

리스트뷰보다 리사이클러뷰를 사용하는 가장 큰 이유는 재사용성이 훨씬 좋기 때문이다

 

# 리사이클러뷰(RecyclerView) 제작

 

1. 해당 xml에 리사이클러뷰(RecyclerView)  생성

우선 지정하고자 하는 해당 뷰의 xml에 RecyclerView 추가한다 여기서는 MainActivity에 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/main_rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="20dp"
        />
</androidx.constraintlayout.widget.ConstraintLayout>

 

2. 리사이클러뷰(RecyclerView)에 들어가는 아이템 xml 생성

리사이클러뷰 속에 들어가는 아이템을 어떻게 만들지 xml을 정의한다.

해당 예제는 아래 사진과 같이 xml를 만들어 보겠다

이미지 뷰 1개, 텍스트 뷰 2개

<recycler_item.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="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <ImageView
        android:id="@+id/item_image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <TextView
        android:id="@+id/item_name_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:layout_marginTop="20dp"
        android:text="이름"
        app:layout_constraintStart_toEndOf="@+id/item_image"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/item_phone_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15sp"
        android:layout_marginTop="60dp"
        android:text="전화번호"
        app:layout_constraintStart_toEndOf="@+id/item_image"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

3. 아이템 클래스 생성

추후 아이템에 어떤 값이 들어갈지 아이템의 클래스를 만들어준다

package com.example.recyclerviewtest

data class RecyclerViewItem(val img : Int, val name : String, val phone : String)

 

4. 어댑터 및 뷰 홀더 상속 / 구현

어댑터 및 뷰 홀더를 상속하여 구현한다.

이때 Inner class로 뷰홀더를 먼저 만들어 준 후 어댑터를 이어 구현해준다.

 

※ ViewHolder - 스크롤을 밑으로 내릴 때, 리사이클러 뷰는 가장 위에 있던 뷰를 가장 아래쪽으로 이동시켜 재활용한다. 즉, 생성과 동시에 정의된 뷰 객체들만 계속해서 위에서 아래로 이동하면서 재사용되는 것이다.

 

따라서 생성된 뷰 객체들에서만 데이터가 수정이 되면 되는 것인데(가장 위의 것이 가장 아래로 갈 때 데이터가 수정)

이 말이 즉슨 뷰 객체를 재사용한다는 의미이고 재사용되는 뷰 객체의 데이터는 계속해서 바뀐다는 것을 의미한다.

따라서 맨 처음 뷰 객체를 기억하고 있을(홀딩) 객체가 필요한데 이 것이 ViewHolder이다. 

 

package com.example.recyclerviewtest

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class RvAdapter : RecyclerView.Adapter<RvAdapter.ViewHolder>() {
    var mData = arrayListOf<RecyclerViewItem>()

    // 아이템 뷰를 저장하는 뷰홀더 클래스
    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val itemImage = itemView.findViewById<ImageView>(R.id.item_image)
        private val itemNameText = itemView.findViewById<TextView>(R.id.item_name_text)
        private val itemPhoneText = itemView.findViewById<TextView>(R.id.item_phone_text)

        fun setData(data : RecyclerViewItem){
            itemImage.setImageResource(data.img)
            itemNameText.text = data.name
            itemPhoneText.text = data.phone
        }
    }


    //아이템 뷰를 위한 뷰홀더 객체를 생성하여 리턴 해준다
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.recycler_item,parent,false))
    }

    // 포지션에 해당하는 데이터를 뷰홀더의 아이템뷰에 표시한다
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = mData[position]
        holder.setData(item)

    }

    // 전체 데이터의 개수를 리턴
    override fun getItemCount(): Int {
        return mData.size
    }

}

 

5.  어댑터와 리사이클러뷰(RecyclerView) 연결(결합) 및 데이터 추가

RecyclerView를 사용하기 위해서는 위에서 만들어준 Adpater와 RecyclerView를 연결해주어야 한다

리사이클러 뷰에 LayoutManager을 설정해야 리사이클러 뷰의 방향을 결정할 수 있다.

현재는 세로로 슬라이딩되도록 하기 위해 VERTICAL을 이용하였다.

 

package com.example.recyclerviewtest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {
    private lateinit var adapterRV: RvAdapter

    val datas = arrayListOf<RecyclerViewItem>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        adapterRV = RvAdapter()

        var rv = findViewById<RecyclerView>(R.id.main_rv)
        rv.setHasFixedSize(true) // 아이템들의 크기가 일정하다는것을 알려줌
        rv.adapter = adapterRV // 리사이클러뷰 어댑터와 만들어준 어댑터 결합
        addItem() // 데이터 추가 함수
        adapterRV.mData = datas
        
        // layoutManager를 이용해 방향설정
        rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

    }

    fun addItem() {
        datas.apply {
            add(RecyclerViewItem(R.drawable.kotlin, "홍길동", "010-1234-4156"))
            add(RecyclerViewItem(R.drawable.an, "홍길동2", "010-1784-4986"))
            add(RecyclerViewItem(R.drawable.kotlin, "홍길동3", "010-8998-4176"))
            add(RecyclerViewItem(R.drawable.an, "홍길동4", "010-7654-6563"))
            add(RecyclerViewItem(R.drawable.kotlin, "홍길동5", "010-0909-5464"))
            add(RecyclerViewItem(R.drawable.an, "홍길동6", "010-6767-1212"))
        }
    }
}

여기까지 오류 없이 잘했으면 완성!!

 

 

참고 : https://www.crocus.co.kr/1704 | https://yunaaaas.tistory.com/43
반응형