[英]IndexOutOfBoundException Inconsistency detected on recyclerview
Hi I am trying to delete an item from recycler view but after successfully deleting when I am scrolling to bottom application is getting crashed and it is showing this error.嗨,我正在尝试从回收站视图中删除一个项目,但是当我滚动到底部时成功删除后,应用程序崩溃并显示此错误。 I tried to call我试着打电话
notifyItemRemoved(position);
notifyItemRangeInserted(position, tasklists.size());
but still its not fixed, I am not sure if I am calling these functions correctly.但它仍然没有修复,我不确定我是否正确调用了这些函数。
2020-05-09 22:09:21.305 10376-10376/com.helpinghandsorg.helpinghands E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.helpinghandsorg.helpinghands, PID: 10376
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 10(offset:10).state:11 androidx.recyclerview.widget.RecyclerView{d7547e3 VFED..... ........ 0,0-1080,1858 #7f0a0159 app:id/recyclerViewTaskLists}, adapter:com.helpinghandsorg.helpinghands.adaptor.MyAdaptor@368f5e0, layout:androidx.recyclerview.widget.LinearLayoutManager@9db2099, context:com.helpinghandsorg.helpinghands.Main2Activity@5c506fd
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6183)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:288)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:345)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:361)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:368)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:399)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7099)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
public class MyAdaptor extends RecyclerView.Adapter<MyAdaptor.myViewHolder> {
private Context context;
private ArrayList<TaskModel> taskLists;
private int counter = 0;
private Boolean success = false;
private String taskid;
private OnTaskClickListner mTaskListner;
private int newPosition;
public MyAdaptor(Context c, ArrayList<TaskModel> t, OnTaskClickListner onTaskClickListner) {
context = c;
taskLists = t;
this.mTaskListner = onTaskClickListner;
}
@NonNull
@Override
public myViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.task_preview, parent, false);
myViewHolder viewHolder = new myViewHolder(view, mTaskListner);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull myViewHolder holder, final int position) {
newPosition = holder.getAdapterPosition();
holder.title.setText(taskLists.get(position).getTaskTitle());
holder.dueDate.setText(taskLists.get(position).getDueDate());
holder.description.setText(taskLists.get(position).getTaskDescription());
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
taskid = taskLists.get(position).getTaskID();
new AlertDialog.Builder(context)
.setTitle(R.string.confirm_text)
.setMessage(R.string.confirm_text_description)
.setPositiveButton(R.string.positive_text, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
FirebaseDatabase.getInstance()
.getReference("tasks")
.child(taskid)
.removeValue(new DatabaseReference.CompletionListener() {
@Override
public void onComplete(@Nullable DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {
taskLists.remove(position);
notifyItemRemoved(position);
Log.d("tasklist", String.valueOf(taskLists.size()));
notifyItemRangeInserted(position, taskLists.size()-1);
Toast.makeText(context, "Delete Successful", Toast.LENGTH_SHORT).show();
}
});
}
})
.setNegativeButton(R.string.negative_text, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).show();
}
});
}
@Override
public int getItemCount() {
return taskLists.size();
}
class myViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView title, dueDate, description;
ImageButton deleteButton;
OnTaskClickListner onTaskClickListner;
public myViewHolder(@NonNull View itemView, OnTaskClickListner onTaskClickListner) {
super(itemView);
title = itemView.findViewById(R.id.taskTitle);
dueDate = itemView.findViewById(R.id.taskDueDate);
description = itemView.findViewById(R.id.taskDescription);
deleteButton = itemView.findViewById(R.id.taskDeleteButton);
this.onTaskClickListner = onTaskClickListner;
itemView.setOnClickListener(this);
}
public ImageButton getDeleteButton() {
return deleteButton;
}
@Override
public void onClick(View v) {
onTaskClickListner.onTaskClick(getAdapterPosition());
}
}
public interface OnTaskClickListner {
void onTaskClick(int position);
}
}
UPDATE: Change position
to holder.getAdapterPosition()
when you need position in anonymous class.and make position non final in onBindViewHolder()
method; UPDATE: Change position
to holder.getAdapterPosition()
when you need position in anonymous class.and make position non final in onBindViewHolder()
method;
public void onBindViewHolder(@NonNull final myViewHolder holder, int position)
and:和:
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
taskid = taskLists.get(holder.getAdapterPosition()).getTaskID();
new AlertDialog.Builder(context)
.setTitle(R.string.confirm_text)
.setMessage(R.string.confirm_text_description)
.setPositiveButton(R.string.positive_text, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
FirebaseDatabase.getInstance()
.getReference("tasks")
.child(taskid)
.removeValue(new DatabaseReference.CompletionListener() {
@Override
public void onComplete(@Nullable DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {
taskLists.remove(holder.getAdapterPosition());
notifyItemRemoved(holder.getAdapterPosition());
Log.d("tasklist", String.valueOf(taskLists.size()));
Toast.makeText(context, "Delete Successful", Toast.LENGTH_SHORT).show();
}
});
}
})
.setNegativeButton(R.string.negative_text, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).show();
}
});
Edit: you must remove notifyItemIRangeInserted()
.when you adding items in your list you must call notifyItemIRangeInserted
.So just call notifyItemRemoved
编辑:您必须删除notifyItemIRangeInserted()
。当您在列表中添加项目时,您必须调用notifyItemIRangeInserted
。所以只需调用notifyItemRemoved
When you are deleting an item you are basically reducing the size of your list, so which also means that the size which you are returning from your getItemCount() should also be reduced.当您删除一个项目时,您基本上是在减小列表的大小,因此这也意味着您从 getItemCount() 返回的大小也应该减小。 Try this: Have a global variable which indicates the size of your list and return that from your getItemCount() when you delete an instance from list, update that variable by decrementing it and then call notifyDataSetChanged()试试这个:有一个全局变量,它指示列表的大小,并在您从列表中删除实例时从 getItemCount() 返回该变量,通过递减该变量来更新该变量,然后调用 notifyDataSetChanged()
The issue, you're using a dynamic list and retrieving data directly from a list that is rather dynamic.问题是,您正在使用动态列表并直接从相当动态的列表中检索数据。 Instead, you should have a global variable inside your adapter and assign the data to it.相反,您应该在适配器内部有一个全局变量并将数据分配给它。 Then, whenever the data changes, you can call "notifyDataSetChanged()".然后,每当数据发生变化时,您都可以调用“notifyDataSetChanged()”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.