我有一个RecyclerView,我使用AsyncTask填充了数据。当我用clear()
和mAdapter.notifyDataSetChanged()
清除列表,然后尝试再次用AsyncTask填充它时,出现此异常:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter position
用我的AsyncTask内的notifyItemInserted()
替换notifyDataSetChanged()
解决了这个问题,但是我认为这不是一个好的解决方案,我想了解为什么第一种方法不起作用。
我的AsyncTask doInBackground()
方法:
@Override protected Void doInBackground(Void... voids) { for (int i = 0; i < 100; i++) { mDataContainer.addItem(i); publishProgress(i); } return null; }
和我的AsyncTask
onProgressUpdate()
方法:
@Override protected void onProgressUpdate(Integer... values) { mAdapter.notifyItemInserted(values[0]); super.onProgressUpdate(values); }
我希望有人可以帮助我。预先感谢。
编辑:这是适配器:
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Item> mItems;
private int selectedPos = RecyclerView.NO_POSITION;
private class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private Item mItem;
private TextView mNameTextView;
private TextView mMembersTextView;
MyViewHolder(View view) {
super(view);
itemView.setOnClickListener(this);
mNameTextView = itemView.findViewById(R.id.item_name);
mMembersTextView = itemView.findViewById(R.id.item_members);
}
@Override
public void onClick(View view) {
notifyItemChanged(selectedPos);
selectedPos = getLayoutPosition();
notifyItemChanged(selectedPos);
mOnItemSelectedListener.onItemSelected(mItem);
}
}
MyAdapter(List<Item> items) {
mItems = items;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(getActivity())
.inflate(R.layout.list_item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder myViewHolder, int position) {
Item item = mItems.get(position);
myViewHolder.mItem = item;
myView.mNameTextView.setText(item.getName());
myView.mMembersTextView.setText(String.format(Locale.US,"%d/50", item.getMembers()));
if (!mIsInit) {
// select item that was selected before orientation change
if (selectedPos != RecyclerView.NO_POSITION) {
Item selectedItem = mItems.get(selectedPos);
mOnItemSelectedListener.onItemSelected(selectedItem);
// else select item 0 as default on landscape mode
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
selectedPos = 0;
mOnItemSelectedListener.onItemSelected(MyViewHolder.mItem);
}
mIsInit = true;
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
myViewHolder.itemView.setSelected(selectedPos == position);
}
}
@Override
public int getItemCount() {
return mItems.size();
}
}
我有一个RecyclerView,我使用AsyncTask填充了数据。当我用clear()和mAdapter.notifyDataSetChanged()清除列表,然后尝试用AsyncTask再次填充它时,我得到了...
我认为最好在后台添加所有值并在插入所有数据后通知适配器“
您只应从UI线程向适配器添加项目(并进行通知)。从后台更改适配器的后备数据,然后稍后通过onProgressUpdate
在UI线程上进行通知很可能会导致争用情况。在这种情况下,在通知适配器之前,应将mDataContainer.addItem(i);
移至onProgressUpdate
。