반응형
이론
리사이클러 뷰의 장점
- 성능 개선: 리사이클러뷰는 스크롤 시 재사용 가능한 뷰를 효율적으로 관리하여 성능을 향상시킵니다. 사용자가 스크롤할 때 불필요한 뷰 생성을 줄이고, 이미 생성된 뷰를 재사용함으로써 메모리 사용을 최적화하고 더 빠른 로딩 시간을 제공합니다.
- 레이아웃 유연성: 리사이클러뷰는 LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager 등 다양한 레이아웃 매니저를 지원하여, 목록을 세로, 가로, 격자형태 등 다양하게 표시할 수 있습니다.
- 애니메이션과 데코레이션 지원: 기본적으로 제공하는 애니메이션 효과들과 아이템 데코레이션 기능을 통해, 목록에 간격을 주거나 구분선을 추가하는 등의 시각적인 개선을 손쉽게 적용할 수 있습니다.
- 확장성: 사용자 정의 뷰홀더와 어댑터 패턴을 사용하여, 각 항목의 레이아웃을 다양하게 구성할 수 있습니다. 이를 통해 다양한 데이터 유형과 복잡한 레이아웃을 효율적으로 처리할 수 있습니다.
- 다양한 이벤트 처리: 아이템 클릭, 롱 클릭, 드래그 앤 드롭, 스와이프 제스처 등 다양한 인터랙션을 손쉽게 구현할 수 있습니다.
리스트 뷰와 다른 점
| 기능 | 리사이클러 뷰 | 리스트 뷰 |
| 뷰 재사용과 성능 | 뷰홀더 패턴을 통한 고성능 뷰 재사용 | 뷰 재사용 가능하지만 뷰홀더 패턴이 없으면 비효율적 |
| 레이아웃 관리 | 다양한 레이아웃 매니저 지원 | 주로 세로 리스트, 격자형은 GridView 필요 |
| 애니메이션과 데코레이션 | 애니메이션 내장, 아이템 데코레이션 지원 | 기본 애니메이션 없음, 구분선 지원 |
| 인터랙션 처리 | 다양한 상호작용(드래그, 스와이프 등) 지원 | 기본 클릭과 롱 클릭 지원만 가능 |
DiffUtil
DiffUtil은 두 리스트 간의 차이점을 계산하는 유틸리티 클래스입니다. 이 클래스는 새 데이터와 기존 데이터 사이의 차이를 계산하고, 이 정보를 바탕으로 리사이클러뷰에 효율적인 업데이트(예: 추가, 삭제, 변경)를 수행할 수 있도록 도와줍니다. DiffUtil은 특히 데이터 변경이 복잡하거나 데이터셋이 큰 경우에 유용하며, UI 스레드의 작업을 최소화하여 더 부드러운 사용자 경험을 제공합니다.
실습
BaseAdapter.kt (베이스 어댑터)
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
abstract class BaseAdapter<T : Any, VB : ViewDataBinding>(
diffCallback: BaseDiffCallback<T>
) : ListAdapter<T, BaseAdapter.BaseViewHolder<VB>>(diffCallback) {
abstract val layoutId: Int
abstract fun bind(binding: VB, item: T)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<VB> {
val binding: VB = DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
layoutId, parent, false
)
return BaseViewHolder(binding)
}
override fun onBindViewHolder(holder: BaseViewHolder<VB>, position: Int) {
bind(holder.binding, getItem(position))
holder.binding.executePendingBindings()
}
class BaseViewHolder<VB : ViewDataBinding>(val binding: VB) : RecyclerView.ViewHolder(binding.root)
}
BaseDiffUtilCallback.kt (베이스 DiffUtil)
package com.example.avocado_android.base
import androidx.recyclerview.widget.DiffUtil
class BaseDiffCallback<T : Any>(
private val itemsTheSame: (oldItem: T, newItem: T) -> Boolean,
private val contentsTheSame: (oldItem: T, newItem: T) -> Boolean
) : DiffUtil.ItemCallback<T>() {
override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
return itemsTheSame(oldItem, newItem)
}
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
return contentsTheSame(oldItem, newItem)
}
}
구현 예시
import com.example.avocado_android.R
import com.example.avocado_android.base.BaseAdapter
import com.example.avocado_android.base.BaseDiffCallback
import com.example.avocado_android.databinding.ItemHomeBestSearchBinding
import com.example.avocado_android.databinding.ItemLibraryWordCardBinding
import com.example.avocado_android.domain.model.response.library.LibraryWordDto
//어댑터의 항목은 아이템 클래스와, 바인딩을 가저옴.
class LibraryCardAdapter : BaseAdapter<LibraryWordDto, ItemLibraryWordCardBinding>(
BaseDiffCallback(
itemsTheSame = { oldItem, newItem -> oldItem == newItem },
contentsTheSame = { oldItem, newItem -> oldItem == newItem }
// 속성 요소, 혹은 속성 자체를 비교
)
) {
override val layoutId: Int
get() = R.layout.item_library_word_card
// 리사이클러뷰 안에 들어갈 아이템 XML을 id로 가저옴.
override fun bind(binding: ItemLibraryWordCardBinding, item: LibraryWordDto) {
binding.libraryData = item
//데이터 바인딩 항목과 아이템을 묶어줌
}
}
연결 예시
private lateinit var libraryAdapter: LibraryCardAdapter
private fun initAdapter() {
libraryViewModel = ViewModelProvider(this)[LibraryViewModel::class.java]
libraryAdapter = LibraryCardAdapter()
//어댑터 생성
with(binding) {
libraryWordCardRv.adapter = libraryAdapter
libraryWordCardRv.addItemDecoration(GridSpacingItemDecoration(spanCount = 2, 16f.fromDpToPx()))
}
//어댑터 연결
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED){
libraryViewModel.wordCardData.collectLatest {response ->
libraryAdapter.submitList(response.libraryWordDtoList)
Glide.with(this@LibraryFragment)
.load(response.characterImgUrl)
.into(binding.libraryLogoImageIv)
}
}
}
//서버에서 온 값을 submitList를 이용하여 리스트를 넣어줌
728x90
반응형
'Android' 카테고리의 다른 글
| Wear Os (워치) (4) | 2024.09.17 |
|---|---|
| PCM (펄스 코드 변조) (5) | 2024.09.09 |
| WebRTC (1) - 웹RTC (스트리밍) (1) | 2024.09.08 |
| Glide 글라이드 (이미지) (2) | 2024.09.07 |
| 안드로이드 포스팅 시작 (0) | 2024.07.26 |