RecycleVIew 调用 notifyItemChanged 那些坑

问题1:最近在项目中遇到一个 物理键盘焦点异常 的问题,每次切换item的时候,焦点总会跳到第一个item的位置,看来看去,原来是这个界面使用了 RecycleView 的问题。在更新数据的时候,调用了 RecyclerViewAdapter.notifyDataSetChanged(),更新了所有item。
解决方法:只更新被选中的item ,调用 RecyclerViewAdapter.notifyItemChanged(index)

切记,要更新的 item 的位置(index)一定要准确,不然找不到指定更新的item,导致调用 RecyclerViewAdapter.notifyItemChanged(index)后,无法正常回调 Adapter方法的 onBindViewHolder(Holder, int)方法

然后发现,焦点问题解决了,新的问题又又又叕来了。。。

问题2:选择item 之后,图片会闪有木有,当然这个问题也不是很难,网上所搜一堆解决方法
解决方法:调用 RecyclerViewAdapter.notifyItemChanged(index, -1)

当然有的解决方案是通过屏蔽动画的方式,来解决刷新时闪动的问题。

((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

但是这个不是闪动的根本原因。下面来看看为什么 图片会闪动一下:

我们先看看 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);
        }
  1. A notifyItemRangeChanged() with null payload will clear all existing payloads on that item.
    —notifyItemRangeChanged() 传入 null payload,会把已经存在的payload清除。
  2. 从这个注释“@param payload Optional parameter, use null to identify a “full” update” 可以看出 如果传入的payload为null,会进行完全更新。

综上,如果调用notifyItemChanged(int position),等效调用notifyItemChanged(position, null),当payload的 参数为 null 时,会进行全局刷新。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值