问题
I'm struggling to implement the funtionality to delete an entry of a recyclerview and re-add it again, if the user decided otherwise. For that I'm showing a Snackbar
with an undo action.
So the flow should be: The user sees a list of Cards
which each show some values and an delete button. If the user presses the delete button, the card is deleted and a Snackbar
is shown. If the user clicks undo on the Snackbar
the Card
should be re-added to the RecyclerView
. Only if the Snackbar
disappears by timeout, the respective entry should also be deleted from SQLite
database.
I'm populating the TextViews
of the respective Cards
and set the OnClickListener
of the delete button in onBindViewHolder
.
My class CardApater
extending RecyclerView.Adapter<CardAdapter.CardViewHolder>
looks like the follwing:
private List<CardEntry> cards;
public CardAdapter(List<CardEntry> cards) {
this.cards = cards;
}
@Override
public int getItemCount() {
return cards.size();
}
@Override
public void onBindViewHolder(final CardViewHolder cardViewHolder, int i) {
final CardEntry card = cards.get(i);
cardViewHolder.tvDate.setText(card.date);
cardViewHolder.tvValue1.setText(card.value1);
cardViewHolder.tvValue2.setText(card.value2);
cardViewHolder.tvValue3.setText(card.value3);
cardViewHolder.deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
cards.remove(cardViewHolder.getAdapterPosition());
notifyDataSetChanged();
Snackbar snack = Snackbar.make(view, "Deleted", Snackbar.LENGTH_LONG);
snack.setAction("Undo", this);
snack.setActionTextColor(Color.RED);
snack.setCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
super.onDismissed(snackbar, event);
switch (event) {
case DISMISS_EVENT_ACTION:
cards.add(card);
notifyDataSetChanged();
break;
case DISMISS_EVENT_TIMEOUT:
MainActivity.datasource.deleteSQLiteEntry(card.id);
break;
}
}
});
snack.show();
}
});
}
@Override
public CardViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.cardview, viewGroup, false);
return new CardViewHolder(itemView);
}
public static class CardViewHolder extends RecyclerView.ViewHolder {
protected TextView tvDate;
protected TextView tvValue1;
protected TextView tvValue2;
protected TextView tvValue3;
protected ImageView deleteButton;
public CardViewHolder(View v) {
super(v);
tvDate = (TextView) v.findViewById(R.id.date);
tvValue1 = (TextView) v.findViewById(R.id.value1);
tvValue2 = (TextView) v.findViewById(R.id.value2);
tvValue3 = (TextView) v.findViewById(R.id.value3);
deleteButton = (ImageView) v.findViewById(R.id.delete);
}
}
Deleting the card works, but when re-adding the CardEntry to the list, the app crashes with ArrayIndexOutOfBoundsException: length=12; index=-1
at the line cards.remove(cardViewHolder.getAdapterPosition());
in the onClick
method.
Any suggestions on that or why onClick
is called at all when adding a new entry are appreciated.
回答1:
This might be because of recycling. The adapter position of the removed card, currently points to nothing. You should keep the position out of the scope of the onBindViewHolder and use that one to re-add it.
来源:https://stackoverflow.com/questions/36497691/deleting-card-from-recyclerview-and-re-add-it-again