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