#1 ListView vs RecyclerView

ํ๋ฉด์ ์์(Item)์ 100๊ฐ ํํํ๋ค๊ณ ํด๋ณด์. ListView๋ GridView ๋ฑ์ ์ ํต์ ์ธ Container Widget๋ค์ ์ด 100๊ฐ์ ์์ดํ
์ ๋ชจ๋ ๋ถ๋ฌ์จ(load)๋ค. ๊ทธ๋ฆฌ๊ณ ํ๋ฉด์ ์คํฌ๋กคํ๋ฉด ๋ฏธ๋ฆฌ Load๋์ด์๋ ์์ดํ
๋ค์ด ๋ณด์ด๋ ๋ฐฉ์์ด๋ค. ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ด ๋ฎ๋ค. ๋ฐ๋ฉด, RecyclerView๋ ์์ดํ
๋ค์ ๋ฏธ๋ฆฌ Loadํด๋์ง ์๋๋ค. ์์ดํ
์ด ํ๋ฉด์ด ๋ณด์ด๊ธฐ ์ง์ ์, ์ด์ ์์ดํ
์ ๊ป๋ฐ๊ธฐ๋ฅผ ์ฌํ์ฉ(Recycle)ํด์ ๊ทธ๋ ๊ทธ๋ Loadํ๋ค.
#2 Adapter
RecyclerView.Adapter | Android Developers
androidx.appsearch.builtintypes.properties
developer.android.com
๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ์ ์์ดํ
ํ๋ํ๋๋ฅผ ViewHolder๋ผ๊ณ ํ๋ค. ๊ทธ๋ฆฌ๊ณ RecyclerView์ ์์ดํ
์ด ํ๋ฉด์ ๋ณด์ด๊ธฐ ์ง์ ์ Load๋๋ ๊ฒ์ ์ด๊ดํ๋ ์ฃผ์ฒด๋ฅผ Adapter๋ผ๊ณ ํ๋ค. ์ด Adapter๋ onCreateViewHolder, onBindViewHolder, getItemCount()์ 3๊ฐ์ง ํต์ฌ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ํ๋ก๊ทธ๋๋จธ๋ ์ด๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ฌ ๊ตฌํํด๋์ด์ผ ํ๋ค. ๊ฐ ๋ฉ์๋์ ์ญํ ์ ๋ค์๊ณผ ๊ฐ๋ค.
#2-1 onCreateViewHolder(): ViewHolder
MainActivity์์์ onCreate()์ ๋น์ทํ๋ค. RecyclerView์์ ๋ณด์ผ Item์ธ ViewHolder๋ฅผ ์์ฑํ๋ค. ๋ณดํต ๋ณ๋์ xml ํ์ผ, ์๋ฅผ ๋ค์ด list_item.xml์ LayoutInflater ํด๋์ค๋ฅผ ์ด์ฉํด View๋ก ๋ง๋ ๋ค.
#2-2 onBindViewHolder()
MainActivity์์์ onStart()์ ๋น์ทํ๋ค. ์ด ๋ฉ์๋์์ ViewHolder์ UI๋ฅผ ์์ฑํ๋ค. onBindViewHolder()์๋ position์ด๋ผ๋ ์ด๋ฆ์ ๋งค๊ฐ๋ณ์๊ฐ ์๋ค. ์ด ๋ณ์๋ #1์ ํ๋ฉด ์ Item ์์ ์จ์ง ์ซ์๋ฅผ ์๋ฏธํ๋ค. position์ 0๋ถํฐ ์์ํ๋ค. ๋ฐ๋ผ์ #1์ "Item 0"๋ถํฐ "Item 99"๊น์ง๊ฐ ์กด์ฌํ๋ค.
#2-3 getItemCount(): Int
Adapter๊ฐ ๊ด๋ฆฌํด์ผํ๋ ViewHolder์ ๊ฐฏ์๋ฅผ ๋ฐํํ๋ค.
#3 RecyclerView ์ฌ์ฉํ๊ธฐ
#3-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/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
#3-2 list_item.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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16sp"
android:background="#BD5151"
android:padding="16sp"
android:text="TextView"
android:textColor="#FFFFFF"
android:textSize="26sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ์ ๋ด๊ธธ ์์ดํ
์ ๋ ์ด์์ ํ์ผ์ด๋ค.
#3-3 MyRecyclerViewAdapter.kt ๋ง๋ค๊ธฐ - 1
// package com.example.recyclerviewbasics
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
class MyRecyclerViewAdapter : RecyclerView.Adapter<MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
TODO("Not yet implemented")
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
TODO("Not yet implemented")
}
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
}
RecyclerView.Adapter๋ฅผ ์์๋ฐ์ ๋ง๋ ๋ค. ๊ทธ๋ฆฌ๊ณ , ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ ์์ ์์ดํ
์ธ ViewHolder ํด๋์ค๋ RecyclerView.ViewHolder๋ฅผ ์์๋ฐ์ ๋ง๋ ๋ค. ViewHolder ํด๋์ค๋ฅผ MyRecyclerViewAdapter.kt ๋ด์ ์ ์ํ๋ ๊ฒ ์๋๋ผ MyViewHolder.kt์ ๊ฐ์ด ๋ณ๋์ ํ์ผ์ ๋ง๋ค์ด ๊ทธ ์์ ๋ง๋ค์ด๋ ๋๋ค. ํ์ง๋ง, ๋ณธ ๊ฒ์๊ธ์์ ์ฌ์ฉํ ViewHolder๋ ViewHolder๊ฐ ์ฐ์ด๋ RecyclerView์ ๊ฐํ๊ฒ ๊ฒฐํฉ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ด๋ ๊ฒ Adapter์ ํด๋์ค ๋ด์ ์ ์ํ๋ค.
#3-4 MyRecyclerViewAdapter.kt ๋ง๋ค๊ธฐ - 2
// package com.example.recyclerviewbasics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class MyRecyclerViewAdapter : RecyclerView.Adapter<MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val listItem = layoutInflater.inflate(R.layout.list_item, parent, false)
return MyViewHolder(listItem)
}
override fun getItemCount(): Int {
return 100
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textItem.text = "Hello\nitem $position"
}
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val textItem: TextView = view.findViewById(R.id.textItem)
}
XML ๋ ์ด์์ ํ์ผ์ ์ค์ ๋ทฐ ๊ฐ์ฒด๋ก ์ธ์คํด์คํํ๋ ๋ฐ ์ฌ์ฉํ๋ ํด๋์ค์ธ LayoutInflater๋ฅผ ์ด์ฉํด ์๊น ๋ง๋ค์ด๋ list_item.xml์ ์ธ์คํด์คํํ๋ค. ์ฌ๊ธฐ์ return๋ ์ธ์คํด์ค๋ ์ฌ์ฉ์์๊ฒ ๋ณด์ด๊ธฐ ์ง์ ์ onBindViewHolder์ ์ํด ๋ด๋ถ ๋ฐ์ดํฐ(์ฌ๊ธฐ์๋ TextView.text)๊ฐ ์ค์ ๋๋ค.
#3-5 MainActivity.kt์์ RecyclerView ๊ฐ์ฒด ์ด๊ธฐํ
// package com.example.recyclerviewbasics
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
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 recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = MyRecyclerViewAdapter()
}
}
๋จผ์ activity_main.xml์ ์๋ ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ ์์ ฏ์ findViewById๋ก ์ฐธ์กฐํ๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น ์์ ฏ์ layoutManager ์์ฑ์ LinearLayoutManager๋ก ์ค์ ํ๋ค. ๋ ์ด์์ ๋งค๋์ ๋ RecyclerView๊ฐ ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ณด์ผ ์ง๋ฅผ ์ ์ํ๋ ๊ฐ์ฒด๋ค. ๋ ์ด์์ ๋งค๋์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager๊ฐ ์๋ค.
LinearLayoutManager๋ ์์ดํ
๋ค์ ์์ง(์ธ๋ก ์คํฌ๋กค) ๋๋ ์ํ(๊ฐ๋ก ์คํฌ๋กค)์ผ๋ก ๋๋ํ ๋ฐฐ์นํ ๋, GridLayoutManager๋ ์์ดํ
๋ค์ GridView์ฒ๋ผ ๊ทธ๋ฆฌ๋์ ๋ฐฐ์นํ ๋, StaggeredGridLayoutManager๋ GridLayoutManager์ ๋น์ทํ์ง๋ง, ๊ทธ๋ฆฌ๋์ ๋ค์ด๊ฐ๋ ๊ฐ ์์ดํ
์ ๋์ด๋ฅผ ๋ค๋ฅด๊ฒ ์ค์ ํ ๋ ์ฌ์ฉํ๋ ๋ ์ด์์ ๋งค๋์ ๋ค. ์ด 3๊ฐ์ ๊ธฐ๋ณธ ๋งค๋์ ์ ๋ํด ๊ตฌํ์ด ์กฐ๊ธ ๋ณต์กํ์ง๋ง, ์ฌ์ฉ์ ์ ์(Custom) ๋ ์ด์์ ๋งค๋์ ๋ฅผ ๋ง๋ค์ด layoutManager ์์ฑ์ ํ ๋นํด์ค ์๋ ์๋ค. ์ด๋ฌํ ๋ ์ด์์์ ์ ์ฐ์ฑ์ ๋ฉ๋ชจ๋ฆฌ ์ฑ๋ฅ ํฅ์ ์ธ ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ์ ์ฅ์ ์ด๋ค.
๋ง์ง๋ง์ผ๋ก, ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ๊ฐ ์ด๋ป๊ฒ ๋์ํ ์ง๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ์ฒด์ธ Adapter๋ฅผ ํ ๋นํ๋ค.
#4 ์๋ ํ์ธ
#4-1 LinearLayoutManager

#4-2 GridLayoutManager
...
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
recyclerView.layoutManager = GridLayoutManager(this, 3)
...
}
}
GridLayoutManager๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ์ ๋์์ด๋ค. 3์ ๋ด๊ฐ ์์๋ก ์ ํ ์ด์ ๊ฐฏ์๋ค. ๋ฐ๋ผ์, 3์ด๋ก ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.

#5 ์์ฝ
๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ๋ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ด ๋๋ค.
#6 ์์ฑ๋ ์ฑ
https://github.com/Kanmanemone/android-practice/tree/master/recycler-view/RecyclerViewBasics
#7 ์ด์ด์ง๋ ๊ธ
[Android] RecyclerView - Adapter์ ์ธ์(Argument) ์ ๋ฌ
#1 ์ด์ ๊ธ [Android] RecyclerView - ๊ธฐ์ด #1 ListView vs RecyclerView ํ๋ฉด์ ์์(Item)์ 100๊ฐ ํํํ๋ค๊ณ ํด๋ณด์. ListView๋ GridView ๋ฑ์ ์ ํต์ ์ธ Container Widget๋ค์ ์ด 100๊ฐ์ ์์ดํ ์ ๋ชจ๋ ๋ถ๋ฌ์จ(load)๋ค. ๊ทธ
kenel.tistory.com
RecyclerView์ Adapter๊ฐ ์ธ์(Argument)๋ฅผ ๋ฐ๊ฒ ๋ง๋ค์ด๋ณธ๋ค.
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Kotlin] Coroutines - LifecycleScope (0) | 2024.02.21 |
---|---|
[Android] RecyclerView - Adapter์ ์ธ์(Argument) ์ ๋ฌ (0) | 2024.02.03 |
[Android] Navigation - ์ ๋๋ฉ์ด์ (1) | 2024.01.27 |
[Android] Navigation - ๊ธฐ์ด (0) | 2024.01.26 |
[Android] Navigation - ํ๊ฒฝ ์ค์ (0) | 2024.01.25 |