RecyclerView通过notifyItemChanged方法更新item避免数据闪烁问题

闪烁主要由于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 时,会进行全局刷新。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值