'Recyclerview notifyItemRemoved removes a wrong item and not working properly when using view binding
When removing an item from recycler view, it is not working properly. For instance, if you remove beginning from the start it removes other items that are not pressed or it won't remove some of them even if you pressed it
Activity Class
List<ModelPlayers> modelPlayers = new ArrayList<>();
modelPlayers.add(new ModelPlayer(R.drawable.photo_ronaldo,"Ronaldo"));
modelPlayers.add(new ModelPlayer(R.drawable.photo_messi,"Messi"));
modelPlayers.add(new ModelPlayer(R.drawable.photo_neymar,"Neymar"));
modelPlayers.add(new ModelPlayer(R.drawable.photo_mbappe,"Mbappe"));
modelPlayers.add(new ModelPlayer(R.drawable.photo_ramos,"Ramos"));
LinearLayoutManager llm= new LinearLayoutManager(activity);
mRecyclerView.setLayoutManager(llm);
mRecyclerView.setHasFixedSize(true);
AdapterPlay adapterPlay= new AdapterPlay(activity, modelPlayers);
mRecyclerView.setAdapter(adapterPlay);
Adapter Class
public class AdapterPlay extends RecyclerView.Adapter<AdapterPlay.PlayerViewHolder> {
public static class PlayerViewHolder extends RecyclerView.ViewHolder {
PlayerViewHolder(View itemView) {
super(itemView);
}
}
private Activity mActivity;
private List<ModelPlayers> modelPlayers = new ArrayList<>();
private ItemPlayBinding mBinding;
public AdapterPlay(Activity activity, List<ModelPlayers> modelPlayers) {
this.mActivity=activity;
this.modelPlayers = modelPlayers;
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
@Override
public PlayerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
mBinding= ItemPlayBinding.inflate(LayoutInflater.from(mActivity),viewGroup,false);
return new PlayerViewHolder(mBinding.getRoot());
}
@Override
public void onBindViewHolder(PlayerViewHolder PlayerViewHolder, int i) {
ModelPlayers modelPlayer = this.modelPlayers.get(i);
mBinding.mainImage.setImageResource(modelPlayer.getImage());
mBinding.mainText.setText(modelPlayer.getTitle());
mBinding.mainText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
modelPlayers.remove(i);
notifyItemRemoved(i);
// notifyItemRangeChanged(i,modelPlays.size());
}
});
}
@Override
public int getItemCount() {
return modelPlayers.size();
}
}
Solution 1:[1]
I finally found out the problem existed because of improper usage of view binding in adapter class.
The changes is only made from the adapter class.
public class AdapterPlay extends RecyclerView.Adapter<AdapterPlay.PlayerViewHolder> {
public static class PlayerViewHolder extends RecyclerView.ViewHolder {
//made changes here, placing the binding here in the viewholder
private ItemPlayBinding mBinding;
PlayerViewHolder(ItemPlayBinding binding){
super(binding.getRoot());
mBinding = binding;
}
}
private Activity mActivity;
private List<ModelPlayer> modelPlayers = new ArrayList<>();
public AdapterPlay(Activity activity, List<ModelPlayer> modelPlayers) {
this.mActivity=activity;
this.modelPlayers = modelPlayers;
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
@Override
public PlayerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
//made changes here
return new PlayerViewHolder(ItemPlayBinding.inflate(
LayoutInflater.from(mActivity),viewGroup,false));
}
@Override
public void onBindViewHolder(PlayerViewHolder playerViewHolder, int i) {
ModelPlayer modelPlayer = this.modelPlayers.get(i);
//instead of the first mbinding.view I know make it viewholder.mbinding.view
playerViewHolder.mBinding.mainImage.setImageResource(modelPlayer.getImage());
playerViewHolder.mBinding.mainText.setText(modelPlayer.getTitle());
playerViewHolder.mBinding.mainText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
modelPlayers.remove(i);
notifyItemRemoved(i);
notifyItemRangeChanged(i,getItemCount());
}
});
}
@Override
public int getItemCount() {
return modelPlayers.size();
}
}
Solution 2:[2]
Man, i had the same problem! Creating the binding inside the ViewHolder like this:
public class MyViewHolder extends RecyclerView.ViewHolder {
ItemProductResumeBinding binding;
public MyViewHolder(ItemProductResumeBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
and inflating it like this:
@NonNull
@Override
public ProductsAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ProductsAdapter.MyViewHolder(ItemProductResumeBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
solved the problem. Thanks! Saved my day!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Aman |
Solution 2 | gnovakovski |