Android RecyclerView滚动使findViewHolderForAdapterPosition返回null

Android RecyclerView滚动使findViewHolderForAdapterPosition返回null,android,nullpointerexception,android-recyclerview,android-adapter,Android,Nullpointerexception,Android Recyclerview,Android Adapter,我有一个带有水平线条布局的RecyclerView。它显示从10到1的数字,用于对某事物进行评级 当我选择10并滚动回1并选择1时。我必须更新UI以删除10上的选择并更新1上的选择。但是,当我使用findViewHolderForAdapterPosition()删除10上的选择时,它会给我一个NullPointerException 我正在使用getAdapterPosition()获取ViewHolder中的位置 然后,通过在我的recycler视图对象上调用FindViewWholderF

我有一个带有水平
线条布局的
RecyclerView
。它显示从10到1的数字,用于对某事物进行评级

当我选择10并滚动回1并选择1时。我必须更新UI以删除10上的选择并更新1上的选择。但是,当我使用
findViewHolderForAdapterPosition()
删除10上的选择时,它会给我一个
NullPointerException

我正在使用
getAdapterPosition()
获取ViewHolder中的位置

然后,通过在我的recycler视图对象上调用
FindViewWholderForAdapterPosition()
来使用该位置获取ViewHolder,并更新UI以从10中删除选择

vh = (RatingRecyclerAdapter.ViewHolder)
                mRecycler.findViewHolderForAdapterPosition(previousPosition);
vh.textRating.setBackgroundResource(R.drawable.rating_background_selected_orange);;
通过一些测试,我发现当我尝试在不滚动的情况下做同样的事情时,效果很好。但是,只有当我滚动时,它才会给我一个
NullPointerException

我该如何解决这个问题

根据要求,这里有一些来自适配器类的重要代码

@Override
public void onBindViewHolder(RatingRecyclerAdapter.ViewHolder holder, int position) {
        String itemText = itemList.get(position);
        holder.textRating.setText(itemText);
}

public class ViewHolder extends RecyclerView.ViewHolder {

        TextView textRating;

        public ViewHolder(View itemView) {
            super(itemView);
            textRating = (TextView) itemView.findViewById(R.id.text_rating);
            textRating.setOnClickListener(ratingClickListener);
        }

        private final View.OnClickListener ratingClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = getAdapterPosition();
                if (callback != null) {
                    callback.onClickRating(v, position);
                }
            }
        };
    }
活动课

@Override
public void onClickRating(View view, int position) {
        RatingRecyclerAdapter.ViewHolder vh;
        int color;

        int previousPosition = mAdapter.getSelectedPosition();  //Get previously clicked postion if any.
        if (previousPosition == Constants.NO_ITEM_SELECTED) {
            // An item was selected first time
            vh = (RatingRecyclerAdapter.ViewHolder)
                    mRecycler.findViewHolderForAdapterPosition(position);
            mAdapter.setSelectedPosition(position);  // Save new item selected position.
            color = Utility.getItemColor(mAdapter.getSelectedRating());
            mAdapter.setSelectedRatingResource(vh, color);
            return;
        }

        if (position == previousPosition) // Same item was selected
            return;

        vh = (RatingRecyclerAdapter.ViewHolder)
                mRecycler.findViewHolderForAdapterPosition(previousPosition);
        color = Utility.getItemColor(mAdapter.getSelectedRating());
        mAdapter.setUnselectedRatingResource(vh, color); // Remove the previous selected item drawables.

        vh = (RatingRecyclerAdapter.ViewHolder)
                mRecycler.findViewHolderForAdapterPosition(position);
        mAdapter.setSelectedPosition(position); // Save new item selected position.
        color = Utility.getItemColor(mAdapter.getSelectedRating());
        mAdapter.setSelectedRatingResource(vh, color); // Set the new selected item drawables. Setting some background to indicate selection.

    }

正如Sevastyan在评论中所写的那样,
RecyclerView
会在项目离开屏幕后立即回收视图。因此,如果我们为屏幕外的视图调用
findViewHolderForAdapterPosition()
,我们会得到一个
null
值。(我不确定这是否是实际情况。但在我看来,这是事实。)

因此,我创建了一个类,用于存储
RecyclerView
中某个项目的所有数据,并将该项目的所有颜色和值存储在该类中。当我们填充视图时,根据该类中存储的数据设置所有颜色


PS:我感谢Sevastyan没有直接给我答案。但是,正如Sevastyan在评论中所写的那样,
RecyclerView
只给了我获取该异常的原因,
RecyclerView
会在项目离开屏幕后立即回收视图。因此,如果我们为屏幕外的视图调用
findViewHolderForAdapterPosition()
,我们会得到一个
null
值。(我不确定这是否是实际情况。但在我看来,这是事实。)

因此,我创建了一个类,用于存储
RecyclerView
中某个项目的所有数据,并将该项目的所有颜色和值存储在该类中。当我们填充视图时,根据该类中存储的数据设置所有颜色


PS:我感谢Sevastyan没有直接给我答案。但是,只告诉我获取该
异常的原因

如果您的视图不在屏幕上,它可以回收缓存

如果是回收的,则可以在onViewRecycled()方法中处理,或者在视图可见时在onBind()中再次设置视图(如果需要,可以保存列表对象的状态)

如果未回收(未为该位置调用onViewRecycled方法),它可能已被缓存。您可以将缓存大小设置为零,以防止发生此状态

recycler.setItemViewCacheSize(0)

如果您的视图不在屏幕上,则可以回收缓存

如果是回收的,则可以在onViewRecycled()方法中处理,或者在视图可见时在onBind()中再次设置视图(如果需要,可以保存列表对象的状态)

如果未回收(未为该位置调用onViewRecycled方法),它可能已被缓存。您可以将缓存大小设置为零,以防止发生此状态

recycler.setItemViewCacheSize(0)

你能发布完整的适配器类吗?你的问题是这可能会帮助你@AmadYus我已经根据请求添加了一些代码。你的
findViewHolderForAdapterPosition()
正在返回
null
,因为请求的ViewHolder已经被回收。我认为您可以通过在
RecyclerView.RecycledViewPool
上调用set
setMaxRecycledViews()
来设置阈值。无论如何,您这样做(在适配器中调用getAdapterPosition())是非常好的。您可以发布完整的适配器类吗?您的问题是,这可能会帮助您@AmadYus我已根据请求添加了一些代码。您的
findViewHolderForAdapterPosition()
正在返回
null
,因为请求的ViewHolder已被回收。我认为您可以通过在
RecyclerView.RecycledViewPool
上调用set
setMaxRecycledViews()
来设置阈值。无论如何,这样做(在适配器中调用getAdapterPosition())非常好。