RecyclerView-当未调用onBindViewHolder时,findViewHolderForPosition始终返回null [英] RecyclerView - findViewHolderForPosition always returns null when onBindViewHolder is not called

查看:62
本文介绍了RecyclerView-当未调用onBindViewHolder时,findViewHolderForPosition始终返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使用新的 RecyclerView 小部件已经存在了几天,以为我已经设法创建了水平"和网格"布局,并且还克服了它缺乏实现OnClickListener的简单方法的事实(我使用了

I've been trying to use the new RecyclerView widget for a couple of days now and thought I've managed to create a Horizontal and Grid layout and also overcome the fact that it lacks of a straightforward way of implementing a OnClickListener (I used GreenRobot's EventBus for this) , I'm still having a hard time selecting an item and preserving that state (style) throughout the recycling process.

这是我用于适配器的代码

This is the code I'm using for my adapter

public class ArticuloItemAdapter extends RecyclerView.Adapter<ArticuloItemAdapter.ItemHolder> {
    private ArrayList<ArticuloObject> mItems;
    private LayoutInflater mLayoutInflater;
    private int mSize;
    private int mSelectedPosition;
    private RecyclerView mRecyclerView;

    public ArticuloItemAdapter(Context context, RecyclerView rv, ArrayList<ArticuloObject> articulos) {

        mLayoutInflater = LayoutInflater.from(context);
        mItems=articulos ;     
        mSize = context.getResources()
                .getDimensionPixelSize(R.dimen.icon);
        mSelectedPosition = -1;
        mRecyclerView = rv;
    }

    @Override
    public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = mLayoutInflater.inflate(R.layout.gallery_recycler_row, parent, false);
        return new ItemHolder(itemView, this);
    }

    @Override
    public void onBindViewHolder(ItemHolder holder, int position) {      
        Ion.with(holder.getPicImageView())
                .placeholder(R.drawable.owner_placeholder)
                .resize(mSize, mSize)
                .centerCrop()
                .error(R.drawable.owner_error)
                .load(mItems.get(position).getUrl());

        //Update the views as they got recycled
        if (mSelectedPosition != position) {
            holder.getPicImageView().setBackgroundColor(Color.TRANSPARENT);
        } else {
            holder.getPicImageView().setBackgroundColor(Color.CYAN);
        }
    }

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

    public int getSelectedPosition() {
        return mSelectedPosition;
    }

    public void setSelectedPosition(int mSelectedPosition) {
        this.mSelectedPosition = mSelectedPosition;
    }

    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    /* Required implementation of ViewHolder to wrap item view */
    public class ItemHolder extends RecyclerView.ViewHolder implements
            View.OnClickListener {
        private ArticuloItemAdapter mParent;
        private ImageView mPicImageView;

        public ItemHolder(View itemView, ArticuloItemAdapter parent) {
            super(itemView);
            itemView.setOnClickListener(this);

            mParent = parent;

            mPicImageView = (ImageView) itemView.findViewById(R.id.picture_image_view);
        }

        public ImageView getPicImageView() {
            return mPicImageView;
        }

        @Override
        public void onClick(View v) {
            EventBus.getDefault().post(new OnArticuloCartaClickEvent(this, getPosition()));
            setItemActivated(v);
        }

        public void setItemActivated(View v) {

            //Check position of previous selected item. The first time an item is selected, the previous position will be  -1
            if (mParent.getSelectedPosition() >= 0) { 
                ItemHolder row = (ItemHolder) mParent.getRecyclerView().findViewHolderForPosition(mParent.getSelectedPosition());
                if (row != null) {
                    row.getPicImageView().setBackgroundColor(Color.TRANSPARENT);
                }
            }
            mParent.setSelectedPosition(getPosition());
            v.findViewById(R.id.picture_image_view).setBackgroundColor(Color.CYAN);

        }
    }

}

现在在上面显示的代码中,我要做的就是跟踪选定的项目:

Now in the code shown above, all I'm doing to keep track of the selected item is the following:

I.在onClick(View v)事件中:

  1. 每当单击一个项目时,我都会调用setItemActivated方法
  2. 在setItemActivated方法中,我检查selectedPosition是否大于或等于0(当未选择任何项目时,默认值为-1).
  3. 如果先前的条件为真,则尝试在该位置获取ViewHolder,并且如果该View不为null,则将ImageView的背景色更改回其原始背景色(透明)
  4. 使用getPosition()
  5. 将mSelectedPosition的新值设置为当前位置
  6. 最后,将当前ViewHolderImageView的背景色更改为其他颜色(在本例中为CYAN)
  1. Whenever an item is clicked, I call the setItemActivated method
  2. In the setItemActivated method, I check if the selectedPosition is greater than or equal to 0 ( the default is -1 when no item is selected).
  3. If the previous condition is true I try to get the ViewHolder in that position and if that View is not null, I change the background colour of the ImageView back to it's original background colour (transparent)
  4. Set the new value of mSelectedPosition to the current position using getPosition()
  5. Finally, change the background colour of the ImageView inside the current ViewHolder to a different colour (CYAN in this case)

II.在onBindViewHolder(ItemHolderholder,int position)方法中:

如果所选项目的位置(mSelectedPosition)与 显示视图的位置,我更改了背景 ImageView的颜色恢复为默认颜色. 否则,我将ImageView的颜色更改为用于标识所选项目的颜色(青色).

If position of selected item (mSelectedPosition) is different from the position of the view being displayed, I change the background colour of the ImageView back to its default colour. Otherwise, I change the colour of the ImageView to the colour used to identify a selected item (CYAN).

只要RecyclerView具有开始回收视图所需的大量项目,所有这些方法都可以使用.但是,如果不是这样,就像我的情况那样,我注意到findViewHolderForPosition总是返回null,结果,我无法将先前选择的项目的颜色改回其默认颜色,所以我最终得到了选择了一个以上的项目.

All this works as long as the RecyclerView has a considerable number of item that it needs to start recycling the views. But if it doesn't, like in my case, I've noticed that findViewHolderForPosition always returns null, and as a result, I cannot change the colour of the previously selected item back to its default colour and so I ended up with more than one item selected.

更糟糕的是,由于RecyclerView不必回收任何东西,因此onBindViewHolder方法永远不会被调用,因此我不能指望内部代码来相应地调整项目的颜色.

And to make matters worse, as the RecyclerView doesn't have to recycle anything, the onBindViewHolder method never gets call and therefore I can't count on the code inside to adjust the colour of the items accordingly.

拜托,如果有人能告诉我我在做什么错,或者提出一些想法,我将非常感激.无法做像选择商品这样的基本工作真令人沮丧.

Please, I'd really appreciate if anyone could tell me what I'm doing wrong here or perhaps give some ideas. It's really frustrating not being able to do something as basic as selecting an item.

谢谢.

推荐答案

这是发生,因为选择的项目发生变化时,你是不是要告诉那个RecyclerView上一个项目是无效的.

This is happening because when selected item changes, you are not telling to RecyclerView that the previous item is invalidated.

执行以下操作,而不是尝试手动进行设置:

Instead of trying to set it manually, do the following:

public void setItemActivated(View v) {
   final int myPos = getAdapterPosition();
   if (myPos == RecyclerView.NO_POSITION) {
       // very rare case where item is clicked but its adapter position 
       // is unknown. ignore the event.
       // See docs of getAdapterPosition for details
   }
   final int prevSelected = mParent.getSelectedPosition();
   mParent.setSelectedPosition(myPos);
   if (prevSelected >= 0 && prevSelected < mParent.getItemCount()) {
       mParent.notifyItemChanged(prevSelected);
   }
   mParent.notifyItemChanged(myPos);
}

RecyclerView将调用onBind以获取应更新的视图.您无需担心先前选择的项目在哪里.

RecyclerView will call onBind for Views that should be updated. You don't need to care about where previous selected item is.

这篇关于RecyclerView-当未调用onBindViewHolder时,findViewHolderForPosition始终返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆