Android에서 RecyclerView와 함께 notifyItemRemoved 또는 notifyDataSetChanged 사용
RecyclerView를 사용하여 표시 할 카드 목록을 만들고 있습니다. 여기서 각 카드에는 목록에서 해당 카드를 제거하는 버튼이 있습니다.
RecyclerView에서 카드를 제거하기 위해 notifyItemRemoved () 를 사용 하면 항목이 제거되고 잘 애니메이션되지만 목록의 데이터가 올바르게 업데이트되지 않습니다.
그 대신 notifyDataSetChanged () 로 전환하면 목록의 항목이 제거되고 올바르게 업데이트되지만 카드는 움직이지 않습니다.
누군가 notifyItemRemoved () 사용 경험이 있고 notifyDataSetChanged와 다르게 작동하는 이유를 알고 있습니까?
다음은 내가 사용하는 코드의 일부입니다.
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);
}
사용 notifyItemRangeChanged (위치에서 getItemCount ()); notifyItemRemoved (position); 후
인덱스를 사용할 필요가없고 위치 만 사용하면됩니다. 아래 코드를 참조하십시오.
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();
}
시도
public void removeItem(int position) {
this.taskLists.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, getItemCount() - position);
}
매력처럼 작동합니다.
내 실수, notifyItemChanged (position) 는 무력합니다. 위치 항목은 제거 할 수 있으며 position + 1 항목은 괜찮지 만 항목은 position + 2에서 시작합니다. 예외가 발생합니다. notifyItemRangeChanged (position, getItemCount) 를 사용하십시오. ()); notifyItemRemoved (position); 후
이렇게 :
public void removeData(int position) {
yourdatalist.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,getItemCount());
}
@pskink가 제안했듯이 내 경우에는 (index + 1)이되어야한다고 제안했듯이 notifyItemRemoved(index+1)
, 아마도 position=0
헤더에 대해 최상위 인덱스를 예약하고 있기 때문일 것입니다 .
당신은 사용할 수 있습니다 getLayoutPosition()
으로부터RecyclerView.ViewHolder
getLayoutPosition()
provides the exact position of item in the layout and code is
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);
}
});
**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;
}
In my case I use Content Provider and a Custom RecyclerView Adapter with Cursor. This line of code is where you notify:
getContext().getContentResolver().notifyChange(uri, null);
Assuming In your recyclerView adapter (Delete Button):
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");
}
And in your Database Provider:
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;
You should add remove listener in ViewHolder class
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);
}
'IT Share you' 카테고리의 다른 글
IE = edge, chrome = 1을 사용하는 것이 여전히 유효합니까? (0) | 2020.11.14 |
---|---|
캔버스 전체를 특정 색상으로 채우는 방법 (0) | 2020.11.14 |
서버 인증서 확인 실패 : 발급자를 신뢰할 수 없습니다. (0) | 2020.11.12 |
자바 스크립트 수학 객체 메소드-음수를 0으로 (0) | 2020.11.12 |
문자열 벡터를 문자열로 내파하는 방법 (우아한 방법) (0) | 2020.11.12 |