728x90
반응형
RecyclerView
RecyclerView는 Android에서 리스트나 그리드 형태의 데이터를 효율적으로 표시하기 위한 강력한 UI 컴포넌트이다.
- RecyclerView는 리스트(ListView)의 개선된 버전으로, 대량의 데이터를 효율적으로 표시하기 위해 설계됨
- 기존의 ListView보다 더 유연하고 성능이 뛰어남
- 이름 그대로 View를 재활용(Recycler) 하여 메모리 사용을 최소화하고 성능을 최적화함
RecyclerView의 핵심요소 3가지
- Adapter (어댑터):
- 데이터와 RecyclerView를 연결하는 브릿지 역할
- 데이터 바인딩 및 ViewHolder 생성 관리
- ViewHolder (뷰홀더):
- 각 항목의 뷰를 재활용하기 위해 사용하는 객체
- 뷰 찾기(findViewId) 성능 최적화
- LayoutManager (레이아웃 매니저):
- 아이템의 배치 방식을 정의 (수평, 수직, 그리드 등)
- 예: LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager
RecyclerView vs ListView
비교 항목 | RecyclerView | ListView |
성능 | View 재활용 최적화, 더 나은 성능 | View 재활용이 제한적, 성능 저하 가능 |
레이아웃 지원 | 수직, 수평, 그리드, 격자 등 다양한 레이아웃 지원 | 기본적으로 수직 리스트만 지원 |
애니메이션 | 기본적으로 애니메이션 지원 | 별도의 구현 필요 |
ViewHolder 패턴 | 강제 적용 | 선택 사항 (권장되지만 필수는 아님) |
데이터 변경 처리 | notifyItemInserted(), notifyItemRemoved() 등 세부 제어 가능 | notifyDataSetChanged()로 전체 갱신 |
RecyclerView 기본 사용법
1. RecyclerView 추가 (XML)
XML 레이아웃 파일 (activity_main.xml)
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp" />
2. ViewHolder 클래스 생성
간단한 name, age 요소를 보유하도록 클래스 생성
class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val nameTextView: TextView = itemView.findViewById(R.id.textName)
val ageTextView: TextView = itemView.findViewById(R.id.textAge)
}
3. Adapter 클래스 생성
User라는 age, name 정보를 가진 데이터 모델이 있다고 가정하여 작성
class UserAdapter(private val userList: List<User>) :
RecyclerView.Adapter<UserViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_user, parent, false)
return UserViewHolder(view)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val user = userList[position]
holder.nameTextView.text = user.name
holder.ageTextView.text = "${user.age}세"
}
override fun getItemCount(): Int = userList.size
}
- onCreateViewHolder(): 아이템 뷰 생성
- onBindViewHolder(): 데이터 바인딩
- getItemCount(): 리스트 항목 개수 반환
4. 아이템 레이아웃 추가 (item_user.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/textName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textAge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp" />
</LinearLayout>
5. MainActivity (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)
val users = listOf(
User("Alice", 25),
User("Bob", 30),
User("Charlie", 28)
)
recyclerView.adapter = UserAdapter(users)
}
}
- LinearLayoutManager: 수직 리스트 형태로 배치
- UserAdapter: 사용자 리스트를 RecyclerView에 연결
6. 아이템 클릭 이벤트 처리
RecyclerView에는 setOnItemClickListener가 기본적으로 존재하지 않으므로, Adapter에서 직접 처리해야 한다.
class UserAdapter(
private val userList: List<User>,
private val onItemClick: (User) -> Unit
) : RecyclerView.Adapter<UserViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_user, parent, false)
return UserViewHolder(view)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val user = userList[position]
holder.nameTextView.text = user.name
holder.ageTextView.text = "${user.age}세"
holder.itemView.setOnClickListener {
onItemClick(user)
}
}
override fun getItemCount(): Int = userList.size
}
MainActivity에서 클릭 이벤트 등록
recyclerView.adapter = UserAdapter(users) { user ->
Toast.makeText(this, "${user.name} 클릭됨!", Toast.LENGTH_SHORT).show()
}
7. 데이터 변경 처리 (DiffUtil 활용)
리스트 데이터가 변경될 때 전체 리스트가 갱신되면 비효율적이다.
DiffUtil을 사용해 변경된 부분만 효율적으로 업데이트할 수 있다.
DiffUtil.ItemCallback 구현
class UserDiffCallback : DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem.name == newItem.name
}
override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}
}
ListAdapter 사용
class UserAdapter : ListAdapter<User, UserViewHolder>(UserDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_user, parent, false)
return UserViewHolder(view)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val user = getItem(position)
holder.nameTextView.text = user.name
holder.ageTextView.text = "${user.age}세"
}
}
데이터 갱신
val newList = listOf(User("David", 35), User("Eve", 29))
(userAdapter as ListAdapter<User, UserViewHolder>).submitList(newList)
submitList()를 호출하면 DiffUtil이 변경된 항목만 효율적으로 업데이트한다.
728x90
반응형
'안드로이드 학습(Kotlin)' 카테고리의 다른 글
16. Glide로 이미지 처리하기 (1) | 2025.02.04 |
---|---|
15. ViewPager의 개념과 구조 (0) | 2025.02.04 |
13. View 이벤트 (키, 포커스) (0) | 2025.02.04 |
12. View 이벤트 (터치) (0) | 2025.02.04 |
11. Activity와 Fragment의 개요 (1) | 2025.02.03 |