RecyclerView 동작 과정
구현하기
1. activity_main.xml 안에 RecyclerView 생성
<?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/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2. RVAdapter라는 코틀린클래스 생성
// RecyclerView.Adapter<RVAdapter.Viewholder>는 RVAdapter.Viewholder를 사용하여 RecyclerView에 데이터를 표시하고 관리하는 데 사용되는 어댑터
// 매개변수로 문자열 데이터의 리스트인 items를 받고 RecyclerView.Adapter를 상속받음
class RVAdapter (val items : MutableList<String>) : RecyclerView.Adapter<RVAdapter.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RVAdapter.ViewHolder {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: RVAdapter.ViewHolder, position: Int) {
TODO("Not yet implemented")
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
}
메서드들
- OnCreateViewHolder : 리사이클러뷰 아이템을 가져옴
- OnBindViewHolder : 뷰 홀더에 바인딩해줌
- getItemCount : 전체 리사이클러뷰의 개수를 알려줌
위의 코드 아래에 ViewHolder를 만들어주자.
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(item : String) {
}
}
getItemCount() 변경
// 전체 리사이클러뷰의 갯수
override fun getItemCount(): Int {
return items.size
}
OnBindViewHolder 변경
함수 내에서 뷰 바인딩을 해줌
override fun onBindViewHolder(holder: RVAdapter.ViewHolder, position: Int) {
// 뷰 바인딩
// RVAdapter의 매개변수인 items를 하나씩 가져와 바인딩을 해줌
holder.bindItems(items[position])
}
뷰 바인딩 : Adapter로 가져온 데이터를 recyclerview_item에 넣어서 recyclerview로 가져오는 작업
OnCreateViewHolder 내에서는 recyclerview_item을 불러와야 한다
이를 위해 먼저 recyclerview_item.xml을 만들어주자
3. rv_item.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="80dp">
<TextView
android:text="rv"
android:textSize="20sp"
android:layout_margin="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
recyclerview_item을 생성했으니 이를 RVAdapter에서 불러오자
OnCreateViewHolder 변경
// recyclerview_item을 불러온다
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RVAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.rv_item, parent, false)
return ViewHolder(view)
}
RVAadapter를 다음과 같이 완성했다
package com.asiae.rv_ex
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
// 매개변수로 문자열 데이터의 리스트인 items를 받고 RecyclerView.Adapter를 상속받음
class RVAdapter (val items : MutableList<String>) : RecyclerView.Adapter<RVAdapter.ViewHolder>(){
// recyclerview_item을 불러온다
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RVAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.rv_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: RVAdapter.ViewHolder, position: Int) {
// 뷰 바인딩
// RVAdapter의 매개변수인 items를 하나씩 가져와 바인딩을 해줌
holder.bindItems(items[position])
}
// 전체 리사이클러뷰의 갯수
override fun getItemCount(): Int {
return items.size
}
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(item : String) {
}
}
}
지금까지 아래의 그림 부분을 하였다
이제 recyclerview_item들을 하나하나 recyclerview에 넣어주면 된다
다시 MainActivity로 와서 데이터를 넣어보자
package com.asiae.rv_ex
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 문자열 데이터를 넣는다
val items = mutableListOf<String>()
items.add("a")
items.add("b")
items.add("c")
// activity_main.xml 내에 있는 리사이클러뷰인 rv를 가져옴
// findViewById를 통해 반환되는 View의 타입이 RecyclerView
val rv = findViewById<RecyclerView>(R.id.rv)
val rvAdapter = RVAdapter(items)
rv.adapter = rvAdapter
rv.layoutManager = LinearLayoutManager(this)
}
}
avdManager를 실행시키면 다음과 같은 화면이 나온다
RVAdapter에 있는 ViewHolder에서 데이터를 안 넣어줬기 때문에 rv가 나온 것이다
그러므로 ViewHolder 내에 있는 bindItems에서 데이터들을 매핑해주어야 한다
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
// bindItems에서 데이터들을 매핑
fun bindItems(item : String) {
// itemView는 rv_item.xml 내에 있는 TextView를 의미
val rv_text = itemView.findViewById<TextView>()
}
}
rv_item.xml에 있는 TextView의 id를 rvItem으로 해줌
<TextView
android:id="@+id/rvItem"
android:text="rv"
android:textSize="20sp"
android:layout_margin="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
다시 RVAdapter로 돌아와 다음 코드 작성
// bindItems에서 데이터들을 매핑
fun bindItems(item : String) {
// rv_item.xml의 rvItem 가져오기
val rv_text = itemView.findViewById<TextView>(R.id.rvItem)
// rv_text의 text값으로 bindItems의 매개변수인 item을 넣어준다
rv_text.text = item
}
MainActivity에 있는 a,b,c가 RVAdapter의 매개변수인 items로 넘어왔고 a,b,c의 하나하나 항목들이 items[position]을 통해 받아지고 bindItems 함수 내부로 와서 각각의 데이터들이 들어가는 형태로 이해하면 된
AVD 실행결과
a,b,c가 잘 들어간 것을 확인할 수 있다
더 나아가기
listview에서는 setOnItemClick(각각의 아이템 클릭)를 해줄 수 있었는데
RecyclerView에서 하려고 하면 다음과 같이 오류가 뜬다
이것을 해주려면 RVAdapter에 직접 선언을 해주어야 하는데 먼저 RVAdapter 내에 다음의 코드를 추가한다
interface ItemClick {
fun onClick(view: View, position: Int)
}
// ?는 nullable 타입을 의미. ItemClick이 'null'일 수도 있다는 것을 나타냄
var itemClick : ItemClick? = null
그 다음 onBindViewHolder 내에 다음의 코드를 추가한다
override fun onBindViewHolder(holder: RVAdapter.ViewHolder, position: Int) {
//추가한 코드
if(itemClick != null) {
holder.itemView.setOnClickListener { v->
itemClick?.onClick(v, position)
}
}
holder.bindItems(items[position])
}
이렇게 추가를 하고 난 뒤 MainActivity로 와서 다음의 코드를 추가한다
// RVAdapter에 선언한 ItemClick 메서드를 가져옴
rvAdapter.itemClick = object : RVAdapter.ItemClick {
override fun onClick(view: View, position: Int) {
// Toast메시지로 몇번째가 클릭되었는지 띄워보자
Toast.makeText(baseContext, items[position], Toast.LENGTH_LONG).show()
}
}
이렇게 하고 avdmanager를 실행하면 각각의 알파벳을 선택할 때마다 그 알파벳에 해당하는 토스트메시지가 뜨는 것을 볼 수 있다
전체 코드는 아래 깃허브의 recyclerview_ex 폴더에서 확인 가능하다
https://github.com/rosa2070/android_kotlin_study
'Android, Kotlin 📱 > [kotlin]앱 8개를 만들면서 배우는 안드로이드 코틀린' 카테고리의 다른 글
[kotlin]섹션 4-3 리스트뷰(ListView)와 어댑터(Adapter)에 관한 설명 (0) | 2023.10.26 |
---|