【问题标题】:RecyclerView index=-1 when scrolling fast to the bottomRecyclerView index=-1 快速滚动到底部时
【发布时间】:2020-07-11 19:31:48
【问题描述】:

我创建了一个RecyclerView 来显示项目,所有内容都显示并且工作正常,除了一种情况:当我快速滚动到RecyclerView 的底部时。

如果这样做,我会收到以下错误:

java.lang.ArrayIndexOutOfBoundsException: length=15; index=-1

它将我引导至我的代码的这一部分(特别是checkIfBorrowed.get( getAdapterPosition() )):

public class itemtestAdapter extends RecyclerView.Adapter<itemtestAdapter.testViewHolder> {

    private List<Discoveritems> items;
    private List<Boolean> checkIftested;

    interface OnItemCheckListener {
        void onItemCheck(Discoveritems items);
        void onItemUncheck(Discoveritems items);
    }

    @NonNull
    private OnItemCheckListener onItemCheckListener;

    public itemtestAdapter(List<Discoveritems> items, List<Boolean> checkIftested, @NonNull OnItemCheckListener onItemCheckListener) {
        this.items = items;
        this.onItemCheckListener = onItemCheckListener;
        this.checkIftested = checkIftested;
    }

    @Override
    public testViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        view = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_item_test_list, parent, false );
        return new testViewHolder(view);
    }

    @Override
    public void onBindViewHolder(testViewHolder holder, int position) {
        holder.bind(items.get(position));

        final Discoveritems currentItem = items.get(position);

        holder.setOnClickListener( v -> {
            holder.Cb_test.setChecked(
                    !holder.Cb_test.isChecked());
            if (holder.Cb_test.isChecked()) {
                onItemCheckListener.onItemCheck(currentItem);
            } else {
                onItemCheckListener.onItemUncheck(currentItem);
            }
        } );

    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    class testViewHolder extends RecyclerView.ViewHolder {
        ImageView Iv_test,itemPic;
        TextView itemName;
        CheckBox Cb_test;
        Discoveritems items;

        public testViewHolder(View itemView) {
            super(itemView);

            Iv_testitemPic = itemView.findViewById(R.id.iv_itemCover);
            Tv_testitemName = itemView.findViewById( R.id.tv_testeditemName);
            Cb_test = itemView.findViewById( R.id.cb_testitem );
            Cb_test.setClickable( false );

        }

        public void setOnClickListener(View.OnClickListener onClickListener) {
            itemView.setOnClickListener(onClickListener);
        }

        public void bind(Discoveritems items) {

            this.items = items;

            String itemID = items.getitemID();
            MyitemClient client = new MyitemClient();
            client.getitems(itemID, new JsonHttpResponseHandler(){
                @Override
                public void onSuccess(int statusCode, Header[] headers, JSONObject response){
                    if(response!=null){
                        final Myitem items = Myitem.fromJson(response);

                        if (checkIftested.get( getAdapterPosition() )){
                            itemView.setEnabled(false);
                            Tv_itemName.setText("my" + items.getTitle());
                        } else {
                            Tv_itemName.setText( items.getTitle() );
                        }
                    }
                }

            });
            
        }
    }

}

问题是在绑定内部,如果不使用getAdapterPosition,我无法弄清楚如何获取项目的位置,而且我也无法理解为什么它只在我快速滚动时才会发生。

另外奇怪的是它说长度 = 15 而 checkIfBorowed 的大小仅为 12。 谢谢

【问题讨论】:

  • 我假设 client.getItems 是异步的?我认为这可能是导致问题的原因。多久调用一次绑定?不止一次对吗?我认为你应该尽量不要在你的绑定函数中做任何异步工作,这可能是最快的解决方案。
  • 是的,它是异步伴侣
  • 那么我认为最简单的方法是确保在绑定时拥有使视图项正确显示所需的所有数据,而不是在绑定方法中异步获取更多数据并成功尝试获取在适配器中的位置。那永远行不通
  • 如果您将holder.bind(items.get(position)); 更改为holder.bind(items.get(position), position);,然后将视图持有者bind 更改为接受新的position 参数,即bind(Discoveritems items, int position) 并使用position 而不是getAdapterPosition(),会发生什么情况?
  • 好像可以,伙计,非常感谢!

标签: java android android-recyclerview android-adapter


【解决方案1】:

holder.bind(items.get(position)); 更改为holder.bind(items.get(position), position);,然后更改视图持有者bind 方法以接受新的位置参数,即bind(Discoveritems items, int position),并使用位置而不是getAdapterPosition()

问题是您没有使用适配器为您的查看器提供的位置,该位置可以在视图被回收时更改,因此它们不适用。更多请看这里https://stackoverflow.com/a/38970513/1133011

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    • 2021-03-28
    • 2014-12-12
    • 1970-01-01
    相关资源
    最近更新 更多