wake-up-neo.com

verwenden von notifyItemRemoved oder notifyDataSetChanged mit RecyclerView in Android

Ich erstelle eine Liste von Karten, die mithilfe der RecyclerView-Karte angezeigt werden sollen, wobei jede Karte über eine Schaltfläche zum Entfernen dieser Karte aus der Liste verfügt.

Wenn ich notifyItemRemoved () verwende, um die Karte in der RecyclerView zu entfernen, wird das Element entfernt und animiert, aber die Daten in der Liste werden nicht korrekt aktualisiert. 

Wenn ich stattdessen zu notifyDataSetChanged () wechsle, werden die Elemente in der Liste entfernt und korrekt aktualisiert. Die Karten werden jedoch nicht animiert.

Hat jemand Erfahrung mit notifyItemRemoved () und weiß, warum es sich anders verhält als notifyDataSetChanged?

Hier ist ein bisschen Code, den ich verwende:

private List<DetectedIssue> issues = new ArrayList<DetectedIssue>();

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element
    if(position >0){
        RiskViewHolder riskHolder = (RiskViewHolder)holder;
        final int index = position - 1;
        final DetectedIssue anIssue = issues.get(index);

        riskHolder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    int index = issues.indexOf(anIssue);
                    issues.remove(anIssue);
                    notifyItemRemoved(index);

                    //notifyDataSetChanged();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

@Override
public int getItemCount() {
    return (issues.size()+1);
}
59
revolutionary

Wie @pskink vorschlug, sollte es in meinem Fall mit notifyItemRemoved(index+1) (Index + 1) sein, wahrscheinlich, weil ich den oberen Index, d. H. position=0, für einen Header reserviere.

0
revolutionary

Verwenden SienotifyItemRangeChanged (position, getItemCount ());after notifyItemRemoved (position);
Sie brauchen keinen Index zu verwenden, verwenden Sie einfach position. Siehe Code unten.

private List<DetectedIssue> issues = new ArrayList<DetectedIssue>();

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element
    if(position >0){
        RiskViewHolder riskHolder = (RiskViewHolder)holder;

        riskHolder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    issues.remove(position);
                    notifyItemRemoved(position);
                    //this line below gives you the animation and also updates the
                    //list items after the deleted item
                    notifyItemRangeChanged(position, getItemCount());

                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

@Override
public int getItemCount() {
    return issues.size();
}
78
Akshay Mahajan

Versucht

public void removeItem(int position) {
    this.taskLists.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, getItemCount() - position);
}

und arbeiten wie ein Zauber.

17
Grender

mein Fehler, notifyItemChanged (position) ist hilflos, das Positionselement kann entfernt werden, und das Item von Position + 1 ist in Ordnung, aber die Elemente beginnen an Position + 2 und erhalten eine Ausnahme Bitte benutzen Sie notifyItemRangeChanged (position, getItemCount ()); after notifyItemRemoved (position);

so was:

public void removeData(int position) {
    yourdatalist.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position,getItemCount());
}
9
TikT

Sie können getLayoutPosition() aus dem RecyclerView.ViewHolder verwenden.

getLayoutPosition() gibt die genaue Position des Artikels im Layout und Code an

holder.removeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Position for remove
                int modPosition= holder.getLayoutPosition();
                //remove item from dataset
                numbers.remove(modPosition);
                //remove item from recycler view
                notifyItemRemoved(modPosition);
            }
        });
0
sree

In meinem Fall verwende ich Content Provider und einen Custom RecyclerView Adapter mit Cursor. In dieser Codezeile werden Sie benachrichtigt:

getContext().getContentResolver().notifyChange(uri, null);

In Ihrem RecyclerView-Adapter (Delete-Button) vorausgesetzt:

Uri currentUri = ContentUris.withAppendedId(DatabaseContract.ToDoEntry.CONTENT_URI_TODO, id);
int rowsDeleted = mContext.getContentResolver().delete(currentUri, null, null);
if (rowsDeleted == 0) {
    Log.d(TAG, "onClick: Delete failed");
} else {
    Log.d(TAG, "onClick: Delete Successful");
}

Und in Ihrem Datenbankanbieter:

case TODO_ID:
selection = DatabaseContract.ToDoEntry._ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
rowsDeleted = database.delete(DatabaseContract.ToDoEntry.TODO_TABLE_NAME, selection, selectionArgs);
if (rowsDeleted != 0){
    getContext().getContentResolver().notifyChange(uri, null);
}
return rowsDeleted;
0
MohammadL
**my solution looks like this**

this way is unnecessary to use the heavy method:
 //notifyItemRangeChanged(xx,xx)

/**
 * 
 * recyclerView的item中的某一个view,获取其最外层的viewParent,也就是item对应的layout在adapter中的position
 *
 * @param recyclerView
 * @param view:can be the deep one inside the item,or the item itself .
 * @return
 */
public static int getParentAdapterPosition(RecyclerView recyclerView, View view, int parentId) {
    if (view.getId() == parentId)
        return recyclerView.getChildAdapterPosition(view);
    View viewGroup = (View) view.getParent();
    if (viewGroup != null && viewGroup.getId() == parentId) {
        return recyclerView.getChildAdapterPosition(viewGroup);
    }
    //recursion
    return getParentAdapterPosition(recyclerView, viewGroup, parentId);
}




//wherever you set the clickListener .
holder.setOnClickListener(R.id.rLayout_device_item, deviceItemClickListener);
holder.setOnLongClickListener(R.id.rLayout_device_item, deviceItemLongClickListener);


@Override
public boolean onLongClick(View v) {
    final int position = ViewUtils.getParentAdapterPosition(rVDevicesList, v, R.id.rLayout_device_item);
    return true;
}
0
dong sheng