我目前有一个回收站视图,其数据每5秒更新一次。要更新列表中的数据,我正在使用
notifyItemChanged(position);
notifyItemRangeChanged(position, mList.size());
每次调用notifyItemChanged()时,我的recycler视图中的项都会正确更新,但是它会闪烁,因为这会导致再次调用onBindViewHolder。所以它似乎每次都是一个新的负载。如果可能的话,我怎样才能防止这种情况发生?
答案 0 :(得分:36)
RecyclerView内置动画,通常可以添加漂亮的抛光效果。在您的情况下,您将要禁用它们:
((SimpleItemAnimator) mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
(默认的回收者视图动画师应该已经是SimpleItemAnimator的实例)
答案 1 :(得分:18)
您可以停用项目动画。
mRecyclerView.setItemAnimator(null);
答案 2 :(得分:1)
问题可能不是来自动画,而是来自not stable id of the list item。
要使用稳定ID,您需要:
-setHasStableIds(true)
在RecyclerView.Adapter中,我们需要设置setHasStableIds(true);。 true表示此适配器将发布唯一值作为数据集中项目的键。通知数据更改后,适配器可以使用该密钥指示它们是否相同。
-覆盖getItemId(int position)
然后,我们必须重写getItemId(int position),以返回针对所定位项目的已确定长度。我们需要确保没有其他具有相同返回ID的商品数据。
该is here的解决方案来源。
答案 3 :(得分:1)
我阅读了以下解决方案并实现了该解决方案,它在我测试的每台设备上都能正常工作。
在animateChange()方法中,在3行以下注释,
final float prevAlpha = oldHolder.itemView.getAlpha();
.
.
oldHolder.itemView.setAlpha(prevAlpha);
.
.
newHolder.itemView.setAlpha(0);
将recyclerview项目动画器设置为克隆类的动画器。
///注:我确实了解该解决方案在不更改新持有人的alpha值的情况下如何工作,但这不是我的解决方案,我在stackoverflow本身上阅读了此内容,但由于某种原因找不到了。分享此内容可以帮助其他开发人员。
答案 4 :(得分:1)
此外,尝试在Main范围内的单独启动的协程作业中运行每个notifyItemChanged。对于我来说,它可以很好地消除眨眼。
for (i in 0 until adapter.itemCount) {
CoroutineScope(Main).launch {
adapter.notifyItemChanged(i)
}
}
答案 5 :(得分:0)
在适配器中使用stableId 。
调用adapter.setHasStableIds(true)
并在您的适配器类中覆盖getItemId(int position)
方法。
还要为每个项目从getItemId(int position)
返回一些唯一的ID。不要只是简单地返回位置。
答案 6 :(得分:0)
就我而言,以上任何内容或其他具有相同问题的stackoverflow问题的答案均无效。
好吧,每次单击该项目时,我都在使用自定义动画,为此我调用notifyItemChanged(int position,Object Payload)将有效负载传递给我的CustomAnimator类。
注意,RecyclerView Adapter中有2种onBindViewHolder(...)方法可用。 具有3个参数的onBindViewHolder(...)方法将始终在具有2个参数的onBindViewHolder(...)方法之前调用。
通常,我们总是重写具有2个参数的onBindViewHolder(...)方法,而问题的主要根源是我在做同样的事情, 每次调用notifyItemChanged(...)时,都会调用我们的onBindViewHolder(...)方法,在该方法中,我使用Picasso将图像加载到ImageView中,这就是无论是否从内存中重新加载图像的原因或通过互联网。在加载之前,它向我显示了占位符图像,这是当我单击itemview时闪烁1秒钟的原因。
稍后,我还将重写另一个具有3个参数的onBindViewHolder(...)方法。在这里,我检查有效载荷列表是否为空,然后返回此方法的超类实现,否则,如果存在有效载荷,我只是将holder的itemView的alpha值设置为1。
是的,可悲的是浪费了一整天之后,我得到了解决问题的方法!
这是我的onBindViewHolder(...)方法的代码:
onBindViewHolder(...)具有2个参数:
@Override
public void onBindViewHolder(@NonNull RecyclerAdapter.ViewHolder viewHolder, int position) {
Movie movie = movies.get(position);
Picasso.with(context)
.load(movie.getImageLink())
.into(viewHolder.itemView.posterImageView);
}
onBindViewHolder(...)带有3个参数:
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
if (payloads.isEmpty()) {
super.onBindViewHolder(holder, position, payloads);
} else {
holder.itemView.setAlpha(1);
}
}
这是我在onCreateViewHolder(...)的viewHolder的itemView的onClickListener中调用的方法的代码:
private void onMovieClick(int position, Movie movie) {
Bundle data = new Bundle();
data.putParcelable("movie", movie);
// This data(bundle) will be passed as payload for ItemHolderInfo in our animator class
notifyItemChanged(position, data);
}
注意:您可以通过从onCreateViewHolder(...)调用viewHolder的getAdapterPosition()方法来获得此位置。
我还重写了getItemId(int position)方法,如下所示:
@Override
public long getItemId(int position) {
Movie movie = movies.get(position);
return movie.getId();
}
并在活动中在我的适配器对象上调用setHasStableIds(true);
。
希望以上方法均不能解决问题!
答案 7 :(得分:0)
如果要保留RecyclerView的动画并避免同时闪烁项目,可以按照以下步骤操作:
1。直接更改视图组件状态
2.直接在适配器中更改数据
3.无需通过调用 notifyItemChanged()
直接更改视图不会立即进行更改,更好的方法是使用payload
进行更改。
在适配器中:
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
// Using payload to refresh partly
if (payloads.isNullOrEmpty()) {
// refresh all
onBindViewHolder(holder, position)
return
}
// just change one component's status which would not "flash".
(holder as YourHolder).apply{
// make you view change
// etc. checkBox.isChecked = true
}
}
并使用它:
yourAdapter.notifyItemChanged(position, "sample_pay_load")
答案 8 :(得分:0)
之所以发生这种情况,是因为Adapter正在创建新的ViewHolder并尝试在新旧的ViewHolders之间建立动画。这就是为什么所有“禁用动画”答案在技术上都起作用的原因。
相反,您只能告诉RecyclerView
与canReuseUpdatedViewHolder()
一起使用Viewholder。看到类似问题的答案:
https://stackoverflow.com/a/60427676/1650674