首页 > 解决方案 > notifyItemChanged 调用 onCreateViewHolder

问题描述

我的 recyclerView 适配器有一个奇怪的问题,我只想根据选择显示/隐藏 ImageView 但是当我notifyItemChanged(selection)在点击侦听器中调用时,它会调用onCreateViewHolder并延迟刷新视图,我不知道为什么而且我没有找到另一种解决方案来执行我需要的操作。

这是我的适配器:

public class ChannelAdapter extends RecyclerView.Adapter<ChannelAdapter.ChannelHolder> {
    private ArrayList<Integer> channelList;
    private Integer selection = 0;

    public ChannelAdapter(ArrayList<Integer> channelList) {
        this.channelList = channelList;
    }

    @NotNull
    @Override
    public ChannelHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.d(TAG, "onCreateViewHolder: ");
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_channel_item_selected, parent, false);
        ChannelHolder holder = new ChannelHolder(view);
        return holder;
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindViewHolder(ChannelHolder holder, int position) {
        Log.d(TAG, "onBindViewHolder: "+position);
        holder.textViewChannelId.setText("#"+channelList.get(position));
        holder.textViewChannel.setText(channelList.get(position).toString());

        if(position==selection){
            holder.imageViewSelectorLeft.setVisibility(View.VISIBLE);
            holder.imageViewSelectorRight.setVisibility(View.VISIBLE);
        }
        else{
            holder.imageViewSelectorLeft.setVisibility(View.INVISIBLE);
            holder.imageViewSelectorRight.setVisibility(View.INVISIBLE);
        }
    }

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

    public class ChannelHolder extends RecyclerView.ViewHolder {
        TextView textViewChannel, textViewChannelId;
        ImageView imageViewSelectorLeft, imageViewSelectorRight;

        public ChannelHolder(View itemView) {
            super(itemView);
            textViewChannelId = itemView.findViewById(R.id.textViewChannelId);
            textViewChannel = itemView.findViewById(R.id.textViewChannel);
            imageViewSelectorLeft = itemView.findViewById(R.id.imageViewSelectorLeft);
            imageViewSelectorRight = itemView.findViewById(R.id.imageViewSelectorRight);

            itemView.setOnClickListener(v -> {
                notifyItemChanged(selection);
                selection=getAdapterPosition();
                notifyItemChanged(selection);
            });
        }
    }
}

我错过了什么还是我做错了?提前感谢您的帮助

编辑: 我尝试使用notifyItemChanged设置为 1 的有效负载并覆盖onBindViewHolder以获取有效负载,但它仍然调用onCreateViewHolder,即使mSupportsChangeAnimations设置为 false

标签: androidandroid-recyclerviewadaptersectionedrecyclerviewadapter

解决方案


默认情况下,您的 RecyclerView 将DefaultItemAnimator附加一个。当你调用notifyItemChanged()你的适配器时,系统最终会调用适配器DefaultItemAnimator来确定它是否需要创建一个新的ViewHolder,或者它是否可以“重用”现有的。

@Override
public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder,
        @NonNull List<Object> payloads) {
    return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}

超类实现:

@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
    return !mSupportsChangeAnimations || viewHolder.isInvalid();
}

这些建议有两种简单的方法可以确保ViewHolder重用而不是重新创建:

  • 确保payloads列表不为空。这是通过调用来完成的adapter.notifyItemChanged(position, payload)payload只要它是非空的,它是什么并不重要。
  • 设置mSupportsChangeAnimationsfalse您的DefaultItemAnimator.
DefaultItemAnimator animator = (DefaultItemAnimator) recyclerView.getItemAnimator();
animator.setSupportsChangeAnimations(false);

推荐阅读