이전 포스팅의 방식대로 recyclerView 를 구현할 때, 데이터가 변경되면 반드시 아래와 같은 notify~ 메서드를 호출해 데이터 변경을 알려주어야 했다. 매번 갱신 코드를 써야하는 것이 굉장히 번거롭다고 생각하던 중 diffUtil 을 적용하는 ListAdapter 에 대해 알게 되어서 이를 사용해보고자 한다.
notifyItemChanged(int)
notifyItemInserted(int)
notifyItemRemoved(int)
notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int)
notifyItemRangeRemoved(int, int)
우선 간단하게 ListAdapter 와 DiffUtil 이 뭔지 그 개념을 정리해보았다.
AsyncListDiffer
ListAdapter
package com.example.presentation.main.view.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.example.domain.model.StudioInfoWithConcept
import com.example.presentation.databinding.ItemResultViewBinding
class ResultViewAdapter : ListAdapter<StudioInfoWithConcept, ResultViewHolder>(StudioDiffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ResultViewHolder {
return ResultViewHolder(
ItemResultViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
override fun onBindViewHolder(holder: ResultViewHolder, position: Int) {
val studio = getItem(position)
holder.bind(studio)
}
companion object {
private val StudioDiffCallback = object : DiffUtil.ItemCallback<StudioInfoWithConcept>() {
override fun areItemsTheSame(oldItem: StudioInfoWithConcept, newItem: StudioInfoWithConcept): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: StudioInfoWithConcept, newItem: StudioInfoWithConcept): Boolean {
return oldItem == newItem
}
}
}
}
package com.example.presentation.main.view.adapter
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.domain.model.StudioInfoWithConcept
import com.example.presentation.databinding.ItemResultViewBinding
import java.util.Locale
class ResultViewHolder(
private val binding: ItemResultViewBinding
) : RecyclerView.ViewHolder(binding.root) {
private val portfolioAdapter = PortfolioAdapter()
fun bind(studio: StudioInfoWithConcept) {
val id = studio.id
val name = studio.name
val rating = studio.rating
val profilePrice = studio.profilePrice
val portfolioUrls = studio.portfolioUrls
val profileURL = studio.profileURL
binding.tvStudioName.text = name
binding.tvRating.text = String.format(Locale.US, "%.1f", rating.toDouble())
imageBind(profileURL)
}
fun imageBind(imageUrl: String) {
Glide.with(binding.root)
.load(imageUrl)
.into(binding.ivStudioMainImage)
}
}
class ResultViewFragment : Fragment(R.layout.fragment_result_view) {
private val viewModel: ResultViewModel by viewModels()
private val sharedViewModel: HomeConceptViewModel by activityViewModels()
private val args: ResultViewFragmentArgs by navArgs()
private lateinit var resultViewAdapter: ResultViewAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val binding = FragmentResultViewBinding.bind(view)
with(binding){
toolbar.setNavigationOnClickListener {
sharedViewModel.onRequestBackPress()
}
}
viewModel.getInitializedStudio(args.conceptId)
setupRvStudioList(binding)
observeResultViewModel()
observeFilterState()
}
private fun setupRvStudioList(binding: FragmentResultViewBinding) {
resultViewAdapter = ResultViewAdapter()
binding.rvStudioList.apply {
layoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
itemAnimator = null
addItemDecoration(
DividerItemDecoration(
requireContext(),
DividerItemDecoration.VERTICAL
)
)
adapter = resultViewAdapter
}
diffUtil 이 백그라운드 스레드에서 데이터를 비교한다기에 백그라운드 스레드가 뭔지 찾아봤다. 메모 메모.
백그라운드 스레드
스레드