闪烁主要由于RecyclerView使用的默认的动画导致的,所以解决的方法就是修改默认的动画。
首先把默认的动画(DefaultItemAnimator)代码复制到自定义的MyItemAnimator类里面。
接着找到animateChangeImpl方法修改其中的两行代码。
// 去掉alpha(0) oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() {...}).start(); oldViewAnim.setListener(new VpaListenerAdapter() {...}).start(); // 去掉alpha(1) newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()). alpha(1).setListener(new VpaListenerAdapter() {...}).start(); newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()). setListener(new VpaListenerAdapter() {...}).start();
最后使用修改后的动画。
recyclerView.setItemAnimator(new MyItemAnimator());
==============================================================================
另一种解决方法:
当然有的解决方案是通过屏蔽动画的方式,来解决刷新时闪动的问题。
((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
1
但是这个不是闪动的根本原因。下面来看看为什么 图片会闪动一下:
我们先看看 notifyItemChanged(int index) 的源码
RecycleView.java
/**
* Notify any registered observers that the item at <code>position</code> has changed.
* Equivalent to calling <code>notifyItemChanged(position, null);</code>.
*
* <p>This is an item change event, not a structural change event. It indicates that any
* reflection of the data at <code>position</code> is out of date and should be updated.
* The item at <code>position</code> retains the same identity.</p>
*
* @param position Position of the item that has changed
*
* @see #notifyItemRangeChanged(int, int)
*/
public final void notifyItemChanged(int position) {
mObservable.notifyItemRangeChanged(position, 1);
}
public void notifyItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart, itemCount, null);
}
public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
// since onItemRangeChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload);
}
}
Equivalent to calling notifyItemChanged(position, null);.
– 从第二行的说明可以看出,调用notifyItemChanged(int position)等效调用notifyItemChanged(position, null);
具体通过 notifyItemRangeChanged 的 payload 传入 null,接着我们看下notifyItemChanged(int position, Object payload)
RecyclerView.java
/**
* Notify any registered observers that the item at <code>position</code> has changed with an
* optional payload object.
*
* <p>This is an item change event, not a structural change event. It indicates that any
* reflection of the data at <code>position</code> is out of date and should be updated.
* The item at <code>position</code> retains the same identity.
* </p>
*
* <p>
* Client can optionally pass a payload for partial change. These payloads will be merged
* and may be passed to adapter's {@link #onBindViewHolder(ViewHolder, int, List)} if the
* item is already represented by a ViewHolder and it will be rebound to the same
* ViewHolder. A notifyItemRangeChanged() with null payload will clear all existing
* payloads on that item and prevent future payload until
* {@link #onBindViewHolder(ViewHolder, int, List)} is called. Adapter should not assume
* that the payload will always be passed to onBindViewHolder(), e.g. when the view is not
* attached, the payload will be simply dropped.
*
* @param position Position of the item that has changed
* @param payload Optional parameter, use null to identify a "full" update
*
* @see #notifyItemRangeChanged(int, int)
*/
public final void notifyItemChanged(int position, Object payload) {
mObservable.notifyItemRangeChanged(position, 1, payload);
}
A notifyItemRangeChanged() with null payload will clear all existing payloads on that item.
—notifyItemRangeChanged() 传入 null payload,会把已经存在的payload清除。
从这个注释“@param payload Optional parameter, use null to identify a “full” update” 可以看出 如果传入的payload为null,会进行完全更新。
综上,如果调用notifyItemChanged(int position),等效调用notifyItemChanged(position, null),当payload的 参数为 null 时,会进行全局刷新。