IndexOutOfBoundsException,在用AsyncTask和notifyItemInserted()重新填充RecyclerView之后,>

问题描述 投票:0回答:2

我有一个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再次填充它时,我得到了...

android android-recyclerview android-asynctask indexoutofboundsexception
2个回答
1
投票

我认为最好在后台添加所有值并在插入所有数据后通知适配器“


0
投票

您只应从UI线程向适配器添加项目(并进行通知)。从后台更改适配器的后备数据,然后稍后通过onProgressUpdate在UI线程上进行通知很可能会导致争用情况。在这种情况下,在通知适配器之前,应将mDataContainer.addItem(i);移至onProgressUpdate

© www.soinside.com 2019 - 2024. All rights reserved.