滚动 RecyclerView 太快时会发生一些奇怪的事情

something weird happens while scrolling RecyclerView too fast

我正在为一个长列表使用 RecyclerView,当我滚动得太快时,会发生一些奇怪的事情。有两个问题。

第一个就是下图中的那个。其中一个项目(如图像中的红色边框)粘在屏幕的某个随机部分并阻挡其他项目。当该项目的真实版本在屏幕上可见时,它就会消失。

滚动这么长的 RecyclerView 太快的另一个问题是卡住 onClick 效果。有些项目变得可见,就像有人在按它们一样。

这些问题是关于我的适配器还是关于 RecyclerView 的常见问题?这是我的适配器:

public class SimpleListItemRecyclerAdapter extends RecyclerView.Adapter<SimpleListItemRecyclerAdapter.ListItemViewHolder> {

    Context context;
    ArrayList<RecyclerItemModel> list;
    OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
    private int lastPosition = -1;
    private boolean isClickable;

    public SimpleListItemRecyclerAdapter(ArrayList<RecyclerItemModel> list, _FragmentTemplate fragment) {
        this.list = list;
        this.context = fragment.getActivity();
        try {
            this.onRecyclerViewItemClickListener = (OnRecyclerViewItemClickListener) fragment;
            isClickable = true;
        } catch (ClassCastException e) {
            isClickable = false;
        }
        setHasStableIds(true);
    }

    @Override
    public ListItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).
                inflate(R.layout.item_sub_main_list_single_text,
                        parent,
                        false);
        return new ListItemViewHolder(itemView, onRecyclerViewItemClickListener, isClickable, list.get(0).getHeight());
    }

    @Override
    public void onBindViewHolder(ListItemViewHolder holder, int position) {
        final RecyclerItemModel recyclerItem = list.get(position);

        if (recyclerItem.isBackgroundColorSpecified())
            holder.itemView.setBackgroundResource(recyclerItem.getBackgroundColorResource());
        else {
            final int[] backgroundColors = Preferences.backgroundSelectorsGrey;
            holder.itemView.setBackgroundResource(backgroundColors[position % backgroundColors.length]);
        }

        holder.textMain.setText(recyclerItem.getTextMain());

        if (recyclerItem.isImageRightAvailable()) {
            if (recyclerItem.isProgressBarAvailable())
                if (recyclerItem.shouldShowDoneImage())
                    setDrawableFromSVG(holder.imageRight, recyclerItem.getImageRightResourceDone());
                else
                    setDrawableFromSVG(holder.imageRight, recyclerItem.getImageRightResource());
        } else
            holder.imageRight.setVisibility(View.GONE);

        if (recyclerItem.isTextMainBottomAvailable())
            holder.textMainBottom.setText(recyclerItem.getTextMainBottom());
        else
            holder.textMainBottom.setVisibility(View.GONE);

        if (recyclerItem.isTextRightTopAvailable())
            holder.textRightTop.setText(recyclerItem.getTextRightTop());
        else
            holder.textRightTop.setVisibility(View.GONE);

        if (recyclerItem.isTextRightBottomAvailable())
            holder.textRightBottom.setText(recyclerItem.getTextRightBottom());
        else
            holder.textRightBottom.setVisibility(View.GONE);

        if (recyclerItem.isProgressBarAvailable())
            holder.progressBar.setProgress(recyclerItem.getProgress());
        else
            holder.progressBar.setVisibility(View.GONE);

        setAnimation(holder.itemView, position);
    }

    @Override
    public long getItemId(int position) {
        return list.get(position).hashCode();
    }

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

    private void setAnimation(View viewToAnimate, int position) {
        if (position > lastPosition) {
            Animation animation = AnimationUtils.loadAnimation(context, R.anim.appear);
            viewToAnimate.startAnimation(animation);
            lastPosition = position;
        }
    }

    public Drawable setDrawableFromSVG(ImageView imageView, int resource) {
        SVG svg = new SVGBuilder()
                .readFromResource(context.getResources(), resource)
                .build();
        imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        imageView.setImageDrawable(svg.getDrawable());
        return svg.getDrawable();
    }

    public final static class ListItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
        TextView textMain, textMainBottom, textRightTop, textRightBottom;
        ImageView imageRight;
        ProgressBar progressBar;
        View itemView;

        public ListItemViewHolder(View itemView, OnRecyclerViewItemClickListener onRecyclerViewItemClickListener,
                                  boolean isClickable, int height) {
            super(itemView);
            this.itemView = itemView;
            this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener;

            textMain = (TextView) itemView.findViewById(R.id.list_item_text_main);
            imageRight = (ImageView) itemView.findViewById(R.id.list_item_image_right);
            textRightTop = (TextView) itemView.findViewById(R.id.list_item_text_right_top);
            textRightBottom = (TextView) itemView.findViewById(R.id.list_item_text_right_bottom);
            textMainBottom = (TextView) itemView.findViewById(R.id.list_item_text_main_bottom);
            progressBar = (ProgressBar) itemView.findViewById(R.id.list_item_progress_bar);

            switch (height) {
                case RecyclerItemModel.HEIGHT_FULL:
                        itemView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, Preferences.squareLength));
                    break;
                case RecyclerItemModel.HEIGHT_HALF:
                        itemView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, Preferences.squareLength / 2));
            }

            if (isClickable)
                itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            onRecyclerViewItemClickListener.onRecyclerViewItemClick(getPosition());
        }
    }
}

这是解决我的问题的方法:

动画以某种方式导致 RecyclerView 出现问题。所以我的解决方案是删除以下行:

setAnimation(holder.itemView, position);

我没有尝试再次添加动画,但如果您真的需要它,这里有一些有用的东西:How to animate RecyclerView items when they appear