У меня есть RecyclerView.inflated из ArrayList объектов. Я добавил кнопку удаления для элемента и хочу удалить элемент, по которому щелкнули мышью. Но при щелчке вместо выбранного элемента удаляется последний элемент. Независимо от того, какой элемент был нажат, всегда удаляется последний элемент. Кто-нибудь знает, почему это происходит?
Адаптер:
public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder> {
private ArrayList<NotificationItem> mNotificationList;
private onItemClickListner mListner;
private Context myContext;
private int layoutResID;
public interface onItemClickListner{
void onItemClick(int position);
void onDeleteClick(int position);
}
// public void setOnItemClickListner(onItemClickListner listner){
// mListner=listner;
// }
//NOTIFICATION HOLDER
public static class NotificationViewHolder extends RecyclerView.ViewHolder{
public TextView mNotificationTextView;
public RelativeLayout mNotificaionHolderLayout;
public ImageView imageDelete;
onItemClickListner listner;
public NotificationViewHolder(View itemView,final onItemClickListner listner) {
super(itemView);
mNotificationTextView=itemView.findViewById(R.id.NotificationTextView);
mNotificaionHolderLayout=itemView.findViewById(R.id.notification__item_container);
imageDelete=itemView.findViewById(R.id.notification_delete_image);
this.listner=listner;
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listner!=null){
int position=getAdapterPosition();
if (position!=RecyclerView.NO_POSITION){
listner.onItemClick(position);
}
}
}
});
imageDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listner!=null){
int position=getAdapterPosition();
if (position!=RecyclerView.NO_POSITION){
listner.onDeleteClick(position);
}
}
}
});
}
}//NOTIFICATION HOLDER
public NotificationAdapter(Context context, int resource, ArrayList<NotificationItem> notificationList,onItemClickListner listner){
myContext=context;
this.layoutResID=resource;
mNotificationList=notificationList;
this.mListner=listner;
}
@Override
public NotificationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v=LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_notificationitem,parent,false);
NotificationViewHolder evh=new NotificationViewHolder(v,mListner);
return evh;
}
@Override
public void onBindViewHolder(NotificationViewHolder holder, int position) {
NotificationItem currentItem=mNotificationList.get(position);
holder.mNotificaionHolderLayout.setBackgroundColor(Color.parseColor(Getcolor(position)));
holder.mNotificationTextView.setText(currentItem.getNotifi_Name());
}
@Override
public int getItemCount() {
return mNotificationList.size();
}
private String Getcolor(int position)
{
String clr;
switch (position)
{
case 0:
clr = "#FF9966";
break;
case 1:
clr = "#009900";
break;
case 2:
clr = "#006699";
break;
case 3:
clr = "#751947";
break;
case 4:
clr = "#FF9966";
break;
case 5:
clr = "#009900";
break;
case 6:
clr = "#006699";
break;
case 7:
clr = "#751947";
break;
default:
clr = "#FFA500";
break;
}
return clr;
}
}
Домашняя активность:
I have implemented the NotificationAdapter in home class and override the functions.and set the adapter to the recycler view.
@Override
public void onItemClick(int position) {
FlashMessage("SOMETHING");
nfAdapter.notifyDataSetChanged();
nfAdapter.notifyItemRemoved(position);
nfAdapter.notifyItemRangeChanged(position,listNotifi.size());
}
@Override
public void onDeleteClick(int position) {
FlashMessage("DELETED ON POSITION : " +position);
listNotifi.remove(position);
nfAdapter.notifyDataSetChanged();
nfAdapter.notifyItemRemoved(position);
nfAdapter.notifyItemRangeChanged(position,listNotifi.size());
}
Поскольку адаптер RecyclerView настроен для повторного использования представлений за пределами экрана, объявление прослушивателя в объявлении ViewHolder является плохой практикой.
Если ваши onClickListeners полагаются на позицию элемента во всем списке, вам нужно знать эту позицию, а не позицию в самом списке адаптеров. (Суть адаптера заключается в том, что он повторно использует свои представления для памяти. Лучше всего оставить класс-держатель для объявления общедоступных переменных для идентификаторов представлений xml.) Просто переместите строки:
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listner!=null){
int position=getAdapterPosition();
if (position!=RecyclerView.NO_POSITION){
listner.onItemClick(position);
}
}
}
});
imageDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listner!=null){
int position=getAdapterPosition();
if (position!=RecyclerView.NO_POSITION){
listner.onDeleteClick(position);
}
}
}
});
в ваш onBindViewHolder, например:
@Override
public void onBindViewHolder(NotificationViewHolder holder, int position) {
NotificationItem currentItem=mNotificationList.get(position);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//listener stuff using position from onBindViewHolder input
}
});
holder.imageDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//listener stuff using position from onBindViewHolder input
}
});
holder.mNotificaionHolderLayout.setBackgroundColor(Color.parseColor(Getcolor(position)));
holder.mNotificationTextView.setText(currentItem.getNotifi_Name());
}
Думаю, это самый простой способ. Возможно, было бы немного более кратко объявить слушателя в адаптере и метод обратного вызова в действии, но это менее подвержено ошибкам. Я думаю, единственная проблема - с памятью для больших списков RV, потому что все слушатели остаются? Я, честно говоря, не уверен в этом прямо сейчас, не перечитав кучу ссылок разработчиков.
да. Это сработало. Использование слушателя в домашнем занятии или держателе не принесет желаемого результата.