In my application I want use RecyclerView
adapter and for set data I used DiffUtils
.
I Want search data from server and then show it into RecyclerView
!
I write below codes, but after search data show items overlay!
I want first clear previous data, then add new items!
Fragment codes :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//InitViews
binding.apply {
searchEdt.addTextChangedListener {
val search = it.toString()
if (search.isNotEmpty()) {
viewModel.searchList.observe(viewLifecycleOwner) { response ->
lastMoviesAdapter.differ.submitList(response.data)
searchMoviesRecycler.initRecycler(LinearLayoutManager(requireContext()), lastMoviesAdapter)
}
viewModel.loadSearchMovies(search)
} else {
Snackbar.make(view, getString(R.string.fillAllFields), Snackbar.LENGTH_SHORT).show()
}
}
Adapter codes:
class LastMoviesAdapter @Inject constructor() : RecyclerView.Adapter<LastMoviesAdapter.ViewHolder>() {
private lateinit var binding: ItemHomeMoviesLastBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
binding = ItemHomeMoviesLastBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder()
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(differ.currentList[position])
holder.setIsRecyclable(false)
}
override fun getItemCount() = differ.currentList.size
inner class ViewHolder : RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(item: Data) {
binding.apply {
moviePosterImg.load(item.poster) {
crossfade(true)
crossfade(1000)
}
movieNameTxt.text = item.title
movieRateTxt.text = item.imdbRating
movieCountryTxt.text = item.country
movieYearTxt.text = item.year
}
}
}
private val differCallback = object : DiffUtil.ItemCallback<Data>() {
override fun areItemsTheSame(oldItem: Data, newItem: Data): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Data, newItem: Data): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, differCallback)
}
How can I fix it?
CodePudding user response:
create a diff utils like this (can do in adapter class)
class DiffUtilCallback(private val oldList: List<Any>, private val newList: List<Any>) :
DiffUtil.Callback() {
// old size
override fun getOldListSize(): Int = oldList.size
// new list size
override fun getNewListSize(): Int = newList.size
// if items are same
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldList[oldItemPosition]
val newItem = newList[newItemPosition]
return oldItem.javaClass == newItem.javaClass
}
// check if contents are same
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldList[oldItemPosition]
val newItem = newList[newItemPosition]
return oldItem.hashCode() == newItem.hashCode()
}
}
then create two methods in your adapter
// set data
fun setData(data: List<Any>) {
this.data = data.toMutableList()
}
// add new data
fun setNewData(newData: List<Any>) {
val diffCallback = DiffUtilCallback(data, newData)
val diffResult = DiffUtil.calculateDiff(diffCallback)
data.clear()
data.addAll(newData)
diffResult.dispatchUpdatesTo(this)
}
in fragment/activity do this
adapter = AdapterDual(recycler, lifecycleScope) // init adapter
adapter.setData(list) // set data
recycler.layoutManager = LinearLayoutManager(activity)
recycler.adapter = adapter // set adapter on recycler
// and when you load new data or replace it
adapter.setNewData(newList)