Reputation: 25
I'm trying to use RecyclerView of android.
1) getItemId() is overridden. 2) setHasStableIds(true) is set.
but Every time notifyDataSetChanged() is called, onBindViewHolder() is called.
I think that if the item id is the same as the existing one, onBindViewHolder() should not be called.
Please let me know my misunderstanding or error in this code.
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ViewHolder> {
private int[] mData = {101, 102, 103, 104, 105};
class ViewHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.text_view);
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
notifyDataSetChanged();
}
});
}
}
public ExampleAdapter() {
setHasStableIds(true);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Log.d("ExampleAdapter", "onBindViewHolder : " + position);
holder.mTextView.setText("data : " + mData[position]);
}
@Override
public int getItemCount() {
return mData.length;
}
@Override
public long getItemId(int position) {
return mData[position];
}
}
Upvotes: 0
Views: 1056
Reputation: 296
[DiffUtil](https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil)
It provides a way to calculate difference between the two list and calls related methods on the adapter like notifyItemInserted(), notifyItemRemoved(), notifyItemChanged(), etc. As a result, the whole list doesn’t get refreshed. Only the items that have been changed are refreshed. It also animates the item changes a little bit so it looks quite nice and it is also performance efficient.
Use of ListAdapter which can simplify the use of DiffUtil on a background thread. So you don't even need to call notifyDataSetChanged().
ListAdapter was added in version 27.1.0 and belongs to maven artifact.
Change Your Adapter to Extend ListAdapter and Create a class extends DiffUtil.Itemcallback. here is my code for reference which is in kotlin.
class AuthorsListAdapter(val clickListner: AuthorClickListner) : ListAdapter<Author,
AuthorsListAdapter.ViewHolder>(AuthorsDiffCallback()) {
//Draw views
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent)
}
//Bind the Values
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position)!!, clickListner)
}
class ViewHolder private constructor(val binding:AuthorsListBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(item: Author, clickListner: AuthorClickListner) {
binding.clicklistner = clickListner
binding.authors= item
binding.executePendingBindings()
}
companion object {
fun from(parent: ViewGroup): ViewHolder {
val binding =
AuthorsListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
}
}
// For Update the differences in list
class AuthorsDiffCallback : DiffUtil.ItemCallback<Author>() {
override fun areItemsTheSame(oldItem: Author, newItem: Author): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Author, newItem: Author): Boolean {
return oldItem == newItem
}
}
class AuthorClickListner(val clickListner: (author:Author) -> Unit)
{
fun onClick(author: Author)
{
clickListner(author)
}
}
Let me know if you still have any queries.
Upvotes: 1