Android 공부/RecyclerView
ListAdapter
posite
2026. 2. 20. 13:42
DiffUtil
- 바뀐 부분만 정확히 계산해서 매번 notifyDataSetChanged()를 호출하는 방식보다 효율적이며, 데이터가 꼬일 가능성을 없애줌
- 백그라운드 처리 및 리스트 관리 직접해야하며 이로 인한 실제 데이터와 소스 간의 싱크가 불일치하는 버그 발생 가능 높음
- 보일러플레이트 코드 다량 발생
val differ = object : DiffUtil.ItemCallback<Meal>() {
override fun areItemsTheSame(oldItem: Meal,newItem: Meal)
= oldItem.idMeal == newItem.idMeal
override fun areContentsTheSame(oldItem: Meal,newItem: Meal) = oldItem == newItem
}
ListAdapter
- DiffUtil 자체적으로 스레드 처리를 해주어 편하게 쓸 수 있음
- ListAdapter 내부적으로 알아서 백그라운드에서 item들을 비교하고 반영함
- currentList라는 단일 진실원칙을 강제하기 때문에 안전함
- submitList() 하나로 리스트 관리가 간편해서 보일러플레이트 코드가 적음
class MealAdapter() : ListAdapter<Meal, MealAdapter.ViewHolder>(differ) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
ItemMealBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
inner class ViewHolder(private val binding: ItemMealBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(data: Meal) {
//Log.d("MealAdapter", "Binding meal data: $data")
Glide.with(binding.root.context)
.load(data.strMealThumb)
.skipMemoryCache(true)
.into(binding.mealImg)
binding.mealName.text = data.strMeal
binding.mealArea.text = data.strArea
binding.mealCategory.text = data.strCategory
binding.mealInstructions.text = data.strInstructions
binding.mealLink.text = data.strYoutube
binding.mealInstructions.setOnClickListener {
Log.d("MealAdapter", "Instructions clicked")
binding.mealInstructions.toggleExpand()
}
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position))
}
}