再说Android RecyclerView局部刷新那个坑

关键:public final void notifyItemChanged(int position, Object payload)

RecyclerView局部刷新大家都遇到过,有时候还说会遇见图片闪烁的问题。

优化之前的效果:

优化之后的效果:

这里写图片描述

如果想单独更新一个item,我们通常会这样做,代码如下:

mLRecyclerViewAdapter.notifyItemChanged(position);

这个也能达到更新的效果,但是有时候却美中不足。那么有没有更好的办法呢?通过查看api,我们发现了另一个方法:

/**
         * Notify any registered observers that the item at position has changed with an
         * optional payload object.
         *
         * 

This is an item change event, not a structural change event. It indicates that any * reflection of the data at position is out of date and should be updated. * The item at position retains the same identity. *

* *

* 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); }

重点看payload参数介绍:

payload Optional parameter, use null to identify a "full" update

翻译过来就是如果payload参数是null,那么就会来一个“完整的”更新,也就是说会全部更新。

下面我们说一下具体怎么使用。

模拟更新一条数据:

int position = 1;//指定列表中的第2个item

            ItemModel itemModel = mDataAdapter.getDataList().get(position);
            itemModel.id = 100;
            itemModel.title = "refresh item " + itemModel.id;
            itemModel.imgUrl = "http://avatar.csdn.net/2/9/C/1_jdsjlzx.jpg";
            mDataAdapter.getDataList().set(position,itemModel);

            //RecyclerView局部刷新  详见:https://github.com/jdsjlzx/LRecyclerView/issues/45
            // notifyItemChanged(int position, Object payload) 其中的payload相当于一个标记,类型不限
            mLRecyclerViewAdapter.notifyItemChanged(mLRecyclerViewAdapter.getAdapterPosition(false,position) , position);

adapter中的onBindViewHolder方法:

@Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            bind(holder,position);
        }

        //局部刷新关键:带payload的这个onBindViewHolder方法必须实现
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) {
            TLog.error("onBindViewHolder payloads.isEmpty() ?  " + payloads.isEmpty() );
            if (payloads.isEmpty()) {
                onBindViewHolder(holder,position);
            } else {//需要更新的数据
                TLog.error("onBindViewHolder payloads.size() =  " + payloads.size());

                //notifyItemChanged(int position, Object payload) 要与payload的类型保持一致
                if (payloads.get(0) instanceof Integer) {
                    bind(holder,position);
                }

            }
        }

上面代码说结合LRecyclerView框架来测试的,想要体验完整demo,请参考:https://github.com/jdsjlzx/LRecyclerView

你可能感兴趣的:(再说Android RecyclerView局部刷新那个坑)