일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 원스휴먼 먹이
- 믹스커피
- 2차 비상계엄
- 원달러환율
- 홈플러스 시그니처 모카골드믹스커피
- 계엄령 외신반응
- 윤석열
- 원스휴먼 요리
- 원스휴먼 스타크롬
- 커피추천
- 믹스커피추천
- 원스휴먼 동물
- 2차계엄
- 원스휴먼 쿠폰
- 국방부
- 일론머스크
- 홈플러스
- 원스휴먼 황금양
- 비상계엄령
- 원스휴먼 황금양 구하기
- 시그니처
- 원스휴먼 사료
- 계엄령
- 원스휴먼 황금양털파밍
- 유광버섯 통조림
- 원스휴먼 레시피 파밍
- 레시피 파밍
- 원스휴먼 레시피
- 1203계엄령
- Today
- Total
0101011001010111
1-3 RecyclerView 본문
앞서 배웠던 CustomView를 이용해서 RecyclerView 라는 걸 할건데,
RecyclerView는 뭐냐면,
한정적인 화면에 많은 데이터를 넣을 수 있는 View입니다.
Recycle = 재활용하다
즉 , View를 재활용해서 사용하겠다는 말이다.
기존의 ListView는 항목을 만들 때마다 새로운 아이템을 계속 뷰 밑으로 생성하게 된다.
▼먼저, ListView는
- 사용자가 스크롤 할 때마다 위에 있던 아이템은 삭제되고, 맨 아래의 아이템은 생성 되길 반복합니다
- 아이템이 100개면 100이 삭제 생성됩니다. 즉 계속 삭제와 생성을 반복하므로 성능에 좋지않습니다.
▼그럼, RecyclerView는
- 사용자가 스크롤 할 때, 위에 있던 아이템은 재활용 돼서 아래로 이동하여 재사용 합니다.
- 즉 아이템이 100개여도 10개정도의 View만 만들고 10개를 재활용해서 사용합니다.
- View를 계속 만드는 ListView의 단점을 보완하기 위해 나왔습니다.
RecyclerView사용하기
Adapter
- Adapter란 데이터 테이블을 목록 형태로 보여주기 위해 사용되는 것으로, 데이터를 다양한 형식의 리스트 형식을 보여주기 위해서 데이터와 RecyclerView 사이에 존재하는 객체이다.
- 즉 데이터와 RecyclerView 사이의 통신을 위한 연결체이다.
▲기존 Adapter와 동일하다.
▼다만, RecyclerView에서만 추가로 들어가는 부분이 있는데,
ViewHolder
- ViewHolder란 화면에 표시될 데이터나 아이템들을 저장하는 역할 입니다. //저장을 해야 뷰를 똑같이 복사해서 불러다 쓰지
- RecyclerView의 개념을 적용하기위해선 스크롤 해서 위로 올라간 View를 재활용하기 위해서 이 View를 기억하고 있어야 합니다. ViewHolder가 그역할을 합니다.
어떻게 만드는지 해보자!
RecyclerView예제
- RecyclerView폴더를 새로 만들고 이전에 실습한 CustomItemView복사한다.
- AndroidStudioFile > Open을 눌러 RecyclerView폴더를 연다.
- 메인화면 레이아웃(예,activity_main.xml)에 ListView위젯을 RecyclerView위젯으로 변경한다.
기존의 activity_main.xml 부분의 ListView를 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/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
ㄴ recyc 치다보면 자동완성으로 나옴
item.xml의 이름을 헷갈리니까 itme_recyclerview.xml로 변경
MyAdapter.kt
class MyAdapter(val mItems: MutableList<MyItem>) : RecyclerView.Adapter<MyAdapter.Holder>() {
interface ItemClick {
fun onClick(view : View, position : Int)
}
var itemClick : ItemClick? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val binding = ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.itemView.setOnClickListener { //클릭이벤트추가부분
itemClick?.onClick(it, position)
}
holder.iconImageView.setImageResource(mItems[position].aIcon)
holder.name.text = mItems[position].aName
holder.age.text = mItems[position].aAge
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemCount(): Int {
return mItems.size
}
inner class Holder(val binding: ItemRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root) {
val iconImageView = binding.iconItem
val name = binding.textItem1
val age = binding.textItem2
}
}
여기서 내가 궁금한건 ItemRecyclerviewBinding 이 item_recyclerview.xml이던데
이름이 다른데 어떻게 이렇게 연결 되는지가 궁금했다.
▼답 :
View Binding의 네이밍 규칙
Android의 View Binding은 XML 파일의 이름을 바탕으로 바인딩 클래스의 이름을 자동으로 생성합니다.
생성 규칙은 다음과 같습니다:
- XML 파일 이름을 카멜 케이스로 변경합니다.
- XML 파일 이름에 포함된 _ (언더바)를 제거합니다.
- XML 파일 이름의 첫 글자를 대문자로 변환합니다.
- 마지막에 "Binding"이라는 단어를 추가합니다.
예를 들어, XML 파일 이름이 item_recyclerview.xml일 때:
- _ (언더바)를 제거합니다. 그러면 itemrecyclerview가 됩니다.
- 첫 글자를 대문자로 바꿉니다. 그러면 Itemrecyclerview가 됩니다.
- 마지막에 "Binding"을 추가하면, 최종적으로 ItemRecyclerviewBinding이 됩니다.
따라서 item_recyclerview.xml 파일은 View Binding을 사용할 때 ItemRecyclerviewBinding이라는 이름의 클래스로 변환됩니다.
올.. 그렇군...
inner class Holder(val binding: ItemRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root) {
val iconImageView = binding.iconItem
val name = binding.textItem1
val age = binding.textItem2
일단 홀더에서는 ,
val iconImageView = binding.iconItem
아이템 뷰는 binding한 iconItem
val name = binding.textItem1
val age = binding.textItem2
이름, 나이 이렇게 해서 홀더를 하나 만들고
그 홀더를,
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
onCreateViewHolder에서 리턴하게 되는거에요 .
또, 리스트에서 한개의 항목을 불러올 때 마다.
override fun onBindViewHolder(holder: Holder, position: Int) {
onBindViewHolder가 생성이 됩니다.
ㄴ 그럼 여기 파라미터에있는
holder와 position을 받아서
holder.itemView.setOnClickListener { //클릭이벤트추가부분
itemClick?.onClick(it, position)
}
holder.iconImageView.setImageResource(mItems[position].aIcon)
holder.name.text = mItems[position].aName
holder.age.text = mItems[position].aAge
해당 홀더에 아이콘, 사진을 넣고 이름과 나이를 집어넣게 돼요.
그래서 RecyclerView의 어탭터는 기존의 커스텀 뷰 어댑터랑 좀 다른 부분은
inner class Holder(val binding: ItemRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root) {
val iconImageView = binding.iconItem
val name = binding.textItem1
val age = binding.textItem2
* 먼저 홀더를 하나 만들어야 한다는거
그리고, onCreateViewHolder에서
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val binding = ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
return Holder를 해야하는거!
(전에 ListView할때는 getView를 했었다. 하지만 RecyclerView에서는 onBindViewHolder로 이런 값을 넣는다.)
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.itemView.setOnClickListener { //클릭이벤트추가부분
itemClick?.onClick(it, position)
}
holder.iconImageView.setImageResource(mItems[position].aIcon)
holder.name.text = mItems[position].aName
holder.age.text = mItems[position].aAge
}
MainActivity
실행해보면 저번에 했던 커스텀뷰와 똑같이 나온다,
mainActivity.kt
package com.example.android_1_2_customviewrecyclerview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.android_1_2_customviewrecyclerview.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.jinju1, "Bella", "1"))
dataList.add(MyItem(R.drawable.jinju2, "Charlie", "2"))
dataList.add(MyItem(R.drawable.jinju3, "Daisy", "1.5"))
dataList.add(MyItem(R.drawable.jinju4, "Duke", "1"))
dataList.add(MyItem(R.drawable.jinju5, "Max", "2"))
dataList.add(MyItem(R.drawable.jinju6, "Happy", "4"))
dataList.add(MyItem(R.drawable.jinju7, "Luna", "3"))
dataList.add(MyItem(R.drawable.jinju8, "Bob", "2"))
val adapter = MyAdapter(dataList)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this)
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()
}
}
}
}
한 번 더 설명을 하자면,
먼저 데이터 클래스가 사용할 아이템에 대한 레이아웃이 먼저 만들어 질 것이고,
그 다음 MyItem 이라는 data class를 만들면 되고,
package com.example.android_1_2_customviewrecyclerview
data class MyItem(val aIcon:Int, val aName:String, val aAge:String) {}
그 다음 리사이클러뷰에 대한 어뎁터는
class MyAdapter(val mItems: MutableList<MyItem>) : RecyclerView.Adapter<MyAdapter.Holder>() {
RecyclerView.Adapter를 상속받아서 아이템을 집어넣고,
그리고 이부분 설명이 빠졌는데
var itemClick : ItemClick? = null
인터페이스를 하나 만들어야 하는데,
리사이클러뷰는 인터페이스를 따로 만들어 줘야 합니다.
그래서 itemClick이라는 아이를 하나 만들고, 그 itemClick은
interface ItemClick {
fun onClick(view : View, position : Int)
}
이 itemClick 인터페이스에 대한 얘를 만들어서
인터페이스 안에는 onClick이 들어가는거구요
그 온클릭은
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.itemView.setOnClickListener { //클릭이벤트추가부분
itemClick?.onClick(it, position)
여기에 들어가게 된다.
아이템이 클릭되게 되면 어탭터와 이 MainActivity사이의 통신을 위해서 만들어준 거다.
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()
그 통신이 어떻게 되냐면 어탭터에서 아이템 클릭 됐을 때, onClick으로 메서트 호출이 되는 거죠.
그래서 어댑터랑 MainActivity와 둘이 통신할 때는 이런식으로 인터페이스를 따로 뺀다는 거 기억하시고 나중에 활용 하시면 될 것 같아요.
'Kotlin > 안드로이드_[숙련]앱개발' 카테고리의 다른 글
kotlin_Dialog (0) | 2023.09.14 |
---|---|
1-4 프래그먼트Fragment (0) | 2023.08.28 |
1-3. CustomView (0) | 2023.08.25 |
1-2.AdapterView_GridView_버튼클릭시 이벤트! (0) | 2023.08.25 |
1-2.AdapterView_GridView_imageVersion (0) | 2023.08.25 |