android android-listview android-recyclerview notifydatasetchanged

utilizando notifyItemRemoved o notifyDataSetChanged con RecyclerView en Android



android-listview android-recyclerview (8)

Como @pskink sugirió que se suponía que era (índice + 1) en mi caso con notifyItemRemoved(index+1) , probablemente porque estoy reservando el índice superior, es decir, position=0 para un encabezado.

Estoy creando una lista de tarjetas para mostrar usando RecyclerView, donde cada tarjeta tiene un botón para quitar esa tarjeta de la lista.

Cuando uso notifyItemRemoved () para eliminar la tarjeta en RecyclerView, elimina el elemento y se anima bien, pero los datos de la lista no se actualizan correctamente.

Si en lugar de eso, cambio a notifyDataSetChanged () , los elementos en la lista se eliminan y actualizan correctamente, pero las tarjetas no se animan.

¿Alguien tiene alguna experiencia en el uso de notifyItemRemoved () y sabe por qué se comporta de manera diferente a notifyDataSetChanged?

Aquí hay un poco de código que estoy usando:

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); }


Debería agregar eliminar oyente en la clase ViewHolder

button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onCancel(getAdapterPosition()); } }); private void onCancel(int position) { if (position >= issues.size()) return; issues.remove(position); notifyItemRemoved(position); }


En mi caso uso Content Provider y Custom RecyclerView Adapter con Cursor. Esta línea de código es donde notificas:

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

Asumiendo en su adaptador recyclerView (botón Eliminar):

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"); }

Y en su proveedor de base de datos:

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;


Intentó

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

y trabajando como un encanto.


Puede usar getLayoutPosition() desde RecyclerView.ViewHolder

getLayoutPosition() proporciona la posición exacta del elemento en el diseño y el código es

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); } });


Use notifyItemRangeChanged (position, getItemCount ()); después de notifyItemRemoved (posición);
No necesita usar índice, solo use posición. Vea el código a continuación.

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(); }


mi error, notifyItemChanged (position) es impotente, el ítem de posición puede ser eliminado, y el ítem de posición + 1 está bien, pero los ítems comienzan desde la posición + 2, obtendrá una excepción, use notifyItemRangeChanged (position, getItemCoged ()); después de notifyItemRemoved (posición);

Me gusta esto:

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


**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; }