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