728x90
리사이클러 뷰 (RecyclerView)
안드로이드 앱에서 리스트 형태의 데이터를 표시하는 데 사용되는 위젯
여러 아이템을 스크롤 가능한 리스트로 표현하며, 많은 아이템을 효율적으로 관리하고 보여주는 역할을 한다
- 한정적인 화면에 많은 데이터를 넣을 수 있는 View
- View를 재활용(Recycle) 해서 사용
리스트 뷰(ListView)와 리사이클러 뷰(RecyclerView)
- 리스트 뷰 (ListView)
- 사용자가 스크롤할 때마다 위에 있던 아이템은 삭제되고, 맨 아래의 아이템은 생성되길 반복한다
- 아이템이 100개면 100이 삭제, 생성을 반복하므로 성능에 좋지 않다
- 리사이클러 뷰 (RecyclerView)
- 사용자가 스크롤할 때, 위에 있던 아이템은 재활용돼서 아래로 이동하여 재사용한다
- 아이템이 100개여도 10개 정도의 View만 만들고 10개를 재활용하여 사용한다
- View를 계속 만드는 리스트 뷰의 단점을 보완하기 위해 나왔다
리사이클러 뷰(RecyclerView) 사용에 필요한 것
1) Adapter
- 데이터 테이블을 목록 형태로 보여주기 위해 사용되는 것으로, 데이터를 다양한 리스트 형식으로 보여주기 위해 데이터와 리사이클 뷰 사이에 존재하는 객체
2) ViewHolder
- 화면에 표시될 데이터나 아이템들을 저장하는 역할
- 리사이클러 뷰의 개념을 적용하기 위해선 스크롤해서 위로 올라간 View를 재활용하기 위해 이 View를 기억하고 있어야 하는데, ViewHolder가 그 역할을 한다
리사이클러 뷰(RecyclerView) 사용하기
예시)
리사이클러 뷰를 사용하기 전, 뷰 바인딩을 추가해 준다
activity_main.xml
더보기
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
item_recyclerview.xml
더보기
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/iconItem"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:padding="8dp"
android:scaleType="centerCrop"
android:src="@drawable/sample_1" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="vertical">
<TextView
android:id="@+id/textItem1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Name"
android:padding="4dp"
android:textColor="#B30B0B"
android:textSize="20dp" />
<TextView
android:id="@+id/textItem2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Num"
android:padding="4dp"
android:textColor="#00FF37"
android:textSize="16dp" />
</LinearLayout>
</LinearLayout>
MyItem.kt (데이터 클래스)
더보기
package com.android.ex_view
data class MyItem(val aIcon:Int, val aName:String, val aNum:String){
}
MainActivity.kt
더보기
package com.android.ex_view
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.ArrayAdapter
import android.widget.LinearLayout
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import com.android.ex_view.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// 데이터 원본 준비
val dataList = mutableListOf<MyItem>()
dataList.add(MyItem(R.drawable.sample_1, "add","1"))
dataList.add(MyItem(R.drawable.sample_2, "search","2"))
dataList.add(MyItem(R.drawable.sample_3, "home","3"))
dataList.add(MyItem(R.drawable.sample_4, "menu","4"))
dataList.add(MyItem(R.drawable.sample_5, "cancel","5"))
dataList.add(MyItem(R.drawable.sample_6, "option","6"))
dataList.add(MyItem(R.drawable.sample_7, "check","7"))
dataList.add(MyItem(R.drawable.sample_8, "plus","8"))
dataList.add(MyItem(R.drawable.sample_9, "delete","9"))
// 어뎁터 생성 후 데이터리스트 넣어줌
val adapter = MyAdapter(dataList)
// 만든 어댑터를 recyclerView 어댑터에 넣어줌
binding.recyclerView.adapter = adapter
// layourManager = 레이아웃 어떻게 구성할건지
binding.recyclerView.layoutManager = LinearLayoutManager(this)
// MyAdapter.kt 36라인에서 받은 클릭이벤트 처리
adapter.itemClick = object : MyAdapter.ItemClick{
override fun onClick(view: View, position: Int) {
val name: String = dataList[position].aName
Toast.makeText(this@MainActivity, "$name 선택!",Toast.LENGTH_SHORT).show()
}
}
}
}
MyAdapter.kt
더보기
package com.android.ex_view
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.android.ex_view.databinding.ItemRecyclerviewBinding
// MyAdapter를 Adapter로 사용하기 위해선 RecyclerView.Adapter를 상속받아야 한다
// <>안에는 뷰홀더를 넣어줘야 함. inner class로 만든 MyAdapter.Holder를 넣어준다
class MyAdapter(val mItems: MutableList<MyItem>) : RecyclerView.Adapter<MyAdapter.Holder>() {
// 클릭 이벤트 추가 부분
interface ItemClick {
fun onClick(view : View, position : Int)
}
// 클릭 이벤트 추가 부분
var itemClick : ItemClick? = null
// viewHolder가 생성되는 함수, 여기서 viewHolder 객체를 생성한다
// 여기서 반환한 뷰 홀더 객체는 자동으로 onBindViewHolder() 함수의 매개변수로 전달된다
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
// 바인딩 선언 후 .inflate() 부분은 공식처럼 생각하면 됨(안바뀜)
val binding = ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
// 중요 // 화면에 보여질 때 실행
// 매개변수로 전달된 뷰 홀더 객체의 뷰에 데이터를 출력하거나 필요한 이벤트를 등록한다
// 매개변수로 있는 position은 아이템 중 지금 아이템이 몇번째 아이템인지 알려준다
override fun onBindViewHolder(holder: Holder, position: Int) {
// 인터페이스 // 클릭 이벤트 추가 부분(여기서 해도 됨) / 지금 이 코드에선 클릭이벤트 받아서 메인액티비티에 보내줌 -> 메인이벤트에서 처리
// 메인액티비티로 보내주려면 메인액티비티랑 어뎁터 사이에 통신가능한 인터페이스를 생성해줘야 함 = 15라인
holder.itemView.setOnClickListener {
itemClick?.onClick(it, position)
}
holder.iconImageView.setImageResource(mItems[position].aIcon)
holder.name.text = mItems[position].aName
holder.num.text = mItems[position].aNum
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
// RecyclerView에 몇가지의 아이템이 떠야되는지 알려주는 메서드
override fun getItemCount(): Int {
return mItems.size
}
// ItemRecylerviewBinding = item_recyclerview.xml 뷰의 홀더, Holder가 계속해서 재활용 됨
inner class Holder(val binding: ItemRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root) {
val iconImageView = binding.iconItem
val name = binding.textItem1
val num = binding.textItem2
}
}
RecyclerView에 adapter를 연결해 줘야 하는데 그 adapter를 만들어 준 것이다
- MyAdapter 생성자는 <MyItem>타입의 MutableList를 받는다고 선언한다
- MyItem은 위에서 만들었던 데이터 클래스 - RecyclerView.Adapter를 상속받은 class MyAdapter()는 필수 구현을 넣어줘야 한다
- ovrride fun onCreateViewHolder / onBindViewHolder / getItemCount
- inner class 홀더명 - inner class로 Holder 클래스를 만들고 생성자로는 viewBinding으로 받아올 binding을 넣는다
- 이 클래스는 뷰홀더로 사용할거니까 RecyclerView.ViewHolder를 상속받아야 한다
- 생성자로는 바로 이전에 만든 binding의 root를 넣는다
728x90
'코틀린(Kotlin) > TIL' 카테고리의 다른 글
[코틀린(Kotlin)] 프래그먼트 데이터 전달 (0) | 2024.01.07 |
---|---|
[코틀린(Kotlin)] 프래그먼트 (Fragment) (0) | 2024.01.07 |
[코틀린(Kotlin)] 어댑터 뷰(AdapterView), 리스트 뷰(ListView), 그리드 뷰(GridView) (1) | 2024.01.05 |
[코틀린(Kotlin)] 뷰바인딩(ViewBinding) (1) | 2024.01.05 |
[코틀린(Kotlin)] 깃 에러 LF CRLF git error (1) | 2024.01.04 |