Android RecyclerView 真正的布局刷新的正确方式

在平时使用RecyclerView时,当想进行布局刷新时,我们通常会调用notifyItemChanged(int positon)进行布局刷新,如果item中图片的话,那么刷新就会出现闪烁,这是怎么回事了? 原因就是notifyItemChanged(int positon)是刷新整个item视图的,也就是重新调用onBindViewHolder方法进行item中所有控件的刷新,这自然会造成图片的重新设置了。
那么如果想要精细到刷新某个item中的某个控件呢?下面我就介绍下recyclerView中真正的布局刷新。

首先需要了解Adapter中的两个方法,一个是三个参数的onBindViewHolder(RecyclerView.ViewHolder holder, int position,List payloads),一个是两个参数的notifyItemChanged(int position, Object payload)。

看起来这2个方法比平时使用的多了一个payload参数,那么这个payload究竟有什么意义呢?在我的理解下,我认为payload可以用来存储一些变量值或者常数,然后在notifyItemChanged中传进去payload,指定某个item进行刷新,在这个Item的onBindViewHolder中就可以从第三个参数拿到传过来的payload。下面看看官方的解释。

* The payloads parameter is a merge list from {@link #notifyItemChanged(int, Object)} or
* {@link #notifyItemRangeChanged(int, int, Object)}.  If the payloads list is not empty,
* the ViewHolder is currently bound to old data and Adapter may run an efficient partial
* update using the payload info.  If the payload is empty,  Adapter must run a full bind.
* Adapter should not assume that the payload passed in notify methods will be received by
* onBindViewHolder().  For example when the view is not attached to the screen, the
* payload in notifyItemChange() will be simply dropped.

* @param payloads A non-null list of merged payloads. Can be empty list if requires full
* update.

也就是说payloads是一个从notifyItemChanged(int, Object)中第二个参数和#notifyItemRangeChanged(int, int, Object)中第三个参数传进来的一个参数。如果payloads不为空并且viewHolder已经绑定了旧数据了,那么adapter会使用payloads参数进行布局刷新。如果payloads为空,adapter就会重新绑定数据,也就是刷新整个item。但是adapter不能保证payload通过nofityItemChanged方法会被onBindViewHolder接收,例如当view没有绑定到screen时,payloads就会失效被丢弃。

{#notifyItemChanged(int, Object)} or { #notifyItemRangeChanged(int, int, Object)}

public final void notifyItemChanged(int position, Object payload) {
            mObservable.notifyItemRangeChanged(position, 1, payload);
        }

public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
            mObservable.notifyItemRangeChanged(positionStart, itemCount, payload);
        }

当我们调用只有一个参数的notifyItemChanged(int position)时 默认payload为null 也即会进行整个itemd的全部刷新,所以会造成图片闪烁的原因就是在这里。

public final void notifyItemChanged(int position) {
            mObservable.notifyItemRangeChanged(position, 1);
        }

mObservable中的notifyItemRangeChanged方法
public void notifyItemRangeChanged(int positionStart, int itemCount) {
            notifyItemRangeChanged(positionStart, itemCount, null);//payload为null 进行整个item的刷新
        }

使用方法:

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    //为空  不使用
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position,List payloads) {
        final ContactHolder contact= (ContactHolder) holder;
        if(payloads.isEmpty()){//payloads为空 即不是调用notifyItemChanged(position,payloads)方法执行的
        //在这里进行初始化item全部控件
           contact.userName.setText(mList.get(position).getName());
           contact.userId.setText(mList.get(position).getId());
           contact.userImg.setImageResources(mList.get(position).getImg());

        }else{//payloads不为空 即调用notifyItemChanged(position,payloads)方法后执行的

            //在这里可以获取payloads中的数据  进行局部刷新
            //假设是int类型
            int type= (int) payloads.get(0);// 刷新哪个部分 标志位
            switch(type){
            case 0:
            contact.userName.setText(mList.get(position).getName());//只刷新userName
            break;
            case 1:
            contact.userId.setText(mList.get(position).getId());//只刷新userId
            break;
            case 2:
            contact.userImg.setImageResources(mList.get(position).getImg());//只刷新userImg
            break;
            }
        }
    }

    public class ContactHolder extends RecyclerView.ViewHolder{
        public CheckBox checkBox;
        public TextView userName;
        public TextView userId;
        public ImageView userImg;

        public ContactHolder(View itemView) {
            super(itemView);
            checkBox= (CheckBox) itemView.findViewById(R.id.ContactSelect_list_item_checkBox);
            userName= (TextView) itemView.findViewById(R.id.ContactSelect_list_item_user_name);
            userId= (TextView) itemView.findViewById(R.id.ContactSelect_list_item_user_employeeId);
            userImg= (ImageView) itemView.findViewById(R.id.ContactSelect_list_item_img);
        }
    }

调用adapter.notifyItemChanged(position,payloads)或者直接在adapter中直接调用notifyItemChanged(position,payloads)进行刷新

mList.get(100).setName("Jason");
notifyItemChanged(100,0);//刷新position为100上的userName
mList.get(102).setName("Yukito");
notifyItemChanged(102,0);//刷新position为102上的userName

mList.get(10).setId("12306");
notifyItemChanged(10,1);//刷新position为10上的userId
mList.get(100).setId("Jason");
mList.get(11).setId("110");
notifyItemChanged(11,0);//刷新position为11上的userId

mList.get(20).setImg(R.drawable.img_one);
notifyItemChanged(20,0);//刷新position为20上的userImg
mList.get(26).setImg(R.drawable.img_two);
notifyItemChanged(26,0);//刷新position为26上的userImg

RecyclerView中实现checkBox单选布局刷新 实战:
http://blog.csdn.net/qq402164452/article/details/53462037

  • 10
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值