美文网首页ard题
RecyclerView<第五篇>:刷新机制

RecyclerView<第五篇>:刷新机制

作者: NoBugException | 来源:发表于2020-02-11 17:25 被阅读0次

    RecyclerView的刷新分为以下两种情况:

    • 刷新的数据量比较大或者刷新Item的位置不确定
    • .刷新指定Item

    1.如果大量的数据被修改或者被修改数据的位置不确定,则使用

    adapter.notifyDataSetChanged();
    

    这个方法很消耗性能,不到万不得已不要使用,请尽量使用下面的刷新方法。

    2.刷新某一项(常用)

    //刷新某Item中的所有组件
    adapter.notifyItemChanged(position);
    //刷新某Item中的部分组件
    adapter.notifyItemChanged(position, payloads);
    //插入Item
    adapter.notifyItemInserted(position);       
    //删除Item
    adapter.notifyItemRemoved(position);  
    //移动Item
    adapter.notifyItemMoved(position, position + 1);
    
    图片.png

    需求1:点击按钮1,使图片和文字改变。

    switch (view.getId()){
        case R.id.image:
            Toast.makeText(MainActivity.this, "点击了图片", Toast.LENGTH_SHORT).show();
            break;
        case R.id.button_1:
            Toast.makeText(MainActivity.this, "点击了按钮1", Toast.LENGTH_SHORT).show();
            PhotoBean photoBean = list.get(position);
            photoBean.setName("修改!");
            photoBean.setUrl("http://pic29.nipic.com/20130511/9252150_174018365301_2.jpg");
            adapter.notifyItemChanged(position);
            break;
         case R.id.button_2:
            Toast.makeText(MainActivity.this, "点击了按钮2", Toast.LENGTH_SHORT).show();
             break;
     }
    
    10.gif

    需求2:点击按钮2,使按钮2高亮。

    首先添加一个clickButton状态

    public class PhotoBean {
    
        private String name;
    
        private String url;
    
        private byte clickButton;//0:点击了图片,1:点击了按钮1,2:点击了按钮2
    
        public PhotoBean(){}
    
        public PhotoBean(String url, String name, byte clickButton){
            this.url = url;
            this.name = name;
            this.clickButton = clickButton;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public byte getClickButton() {
            return clickButton;
        }
    
        public void setClickButton(byte clickButton) {
            this.clickButton = clickButton;
        }
    }
    

    修改onBindViewHolder方法,将按钮变黄

        @Override
        public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
            PhotoBean dataListBean = mData.get(position);
    
            if(dataListBean != null){
    
                Glide.with(mContext).load(dataListBean.getUrl()).into(((ViewHolder)holder).imgView);
                ((ViewHolder)holder).tvName.setText(dataListBean.getName());
    
                if(dataListBean.getClickButton() == 2){
                    ((ViewHolder)holder).button_2.setBackgroundColor(Color.YELLOW);
                }
            }
    
            ((ViewHolder)holder).imgView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickLitener != null) {
                        if(mData != null && mData.size() > 0){
                            mOnItemClickLitener.onItemClick(((ViewHolder)holder).imgView, position);
                        }
                    }
                }
            });
    
            ((ViewHolder)holder).button_1.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickLitener != null) {
                        if(mData != null && mData.size() > 0){
                            mOnItemClickLitener.onItemClick(((ViewHolder)holder).button_1, position);
                        }
                    }
                }
            });
    
            ((ViewHolder)holder).button_2.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickLitener != null) {
                        if(mData != null && mData.size() > 0){
                            mOnItemClickLitener.onItemClick(((ViewHolder)holder).button_2, position);
                        }
                    }
                }
            });
        }
    

    效果如下:


    11.gif

    这样貌似已经实现了功能,但是存在两个严重的弊端:
    1.我只要将按钮2改变颜色就行了,为什么图片还会刷新?
    2.我每次点击按钮2,图片、文字、按钮都要重新排版一次,严重消耗性能,也许现在手机性能比较好,很多人不在乎,但是我在乎。

    解决方案:使用payloads实现刷新Item中的部分控件。

    修改按钮2点击事件实现

    case R.id.button_2:
         Toast.makeText(MainActivity.this, "点击了按钮2", Toast.LENGTH_SHORT).show();
         PhotoBean photoBean2 = new PhotoBean();
         photoBean2.setClickButton((byte) 2);
         adapter.notifyItemChanged(position, photoBean2);
          break;
    

    添加回调方法

        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
            if(payloads != null && !payloads.isEmpty()){
                if(payloads.get(0) instanceof PhotoBean){
                    PhotoBean photoBean = (PhotoBean) payloads.get(0);
    
                    if(photoBean.getClickButton() == 2){
                        ((ViewHolder)holder).button_2.setBackgroundColor(Color.YELLOW);
                    }
                }
    
            }else{
                onBindViewHolder(holder, position);
            }
        }
    

    展示效果

    12.gif

    需求3:实现添加删除和移动功能

    case R.id.button_3:
         Toast.makeText(MainActivity.this, "添加Item", Toast.LENGTH_SHORT).show();
         list.add(position, new PhotoBean(list.get(position).getUrl(), list.get(position).getName(), list.get(position).getClickButton()));
         adapter.notifyItemInserted(position);
         break;
    case R.id.button_4:
         Toast.makeText(MainActivity.this, "删除Item", Toast.LENGTH_SHORT).show();
         list.remove(position);
         adapter.notifyItemRemoved(position);
         break;
    case R.id.button_5:
         Toast.makeText(MainActivity.this, "移动Item", Toast.LENGTH_SHORT).show();
         Collections.swap(list,position,position+1);// 元素互换
         adapter.notifyItemMoved(position, position + 1);
         break;
    

    添加效果:


    13.gif

    删除效果:


    14.gif

    移动效果:


    15.gif

    另外,以上讲解的都是刷新一个Item, 下面四个方法是更新多个Item

    public final void notifyItemRangeChanged(int positionStart, int itemCount);
    public final void notifyItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload);
    public final void notifyItemRangeInserted(int positionStart, int itemCount);
    public final void notifyItemRangeRemoved(int positionStart, int itemCount) ;
    

    其实,更新一个Item的方法,底层都会调用以上四个方法的其中一个,只是此时itemCount=1。

    需要注意的是:

        mRecyclerView.setHasFixedSize(false);
    

    您可能还需要知道setHasFixedSize的的使用。

    • 当setHasFixedSize为true时,Item高度变化时,不会重新计算高度;
    • 当setHasFixedSize为false时,Item高度变化时,会重新计算高度;

    setHasFixedSize默认是false。
    当执行

    onItemRangeChanged()
    onItemRangeInserted()
    onItemRangeRemoved()
    onItemRangeMoved()
    

    时,可以设置setHasFixedSize为true,让Item的高度不会重新计算,这样可以保证性能。

    如果调用了notifyDataSetChanged,Item的大小总是会被重新计算。

    大家可以参考一下文章:

    RecyclerView性能优化:setHasFixedSize

    [本章完...]

    相关文章

      网友评论

        本文标题:RecyclerView<第五篇>:刷新机制

        本文链接:https://www.haomeiwen.com/subject/yqgxfhtx.html