美文网首页
diffutil 的方法介绍

diffutil 的方法介绍

作者: 坚持编程_lyz | 来源:发表于2017-05-03 23:01 被阅读151次
    package com.mcxtzhang.diffutils.diffutil;
    
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v7.util.DiffUtil;
    import android.support.v7.widget.RecyclerView;
    
    import java.util.List;
    
    /**
     * 介绍:核心类 用来判断 新旧Item是否相等
     * 作者:zhangxutong
     * 邮箱:zhangxutong@imcoming.com
     * 时间: 2016/9/12.
     */
    
    public class DiffCallBack extends DiffUtil.Callback {
        private List<TestBean> mOldDatas, mNewDatas;//看名字
    
        public DiffCallBack(List<TestBean> mOldDatas, List<TestBean> mNewDatas) {
            this.mOldDatas = mOldDatas;
            this.mNewDatas = mNewDatas;
        }
    
        //老数据集size
        @Override
        public int getOldListSize() {
            return mOldDatas != null ? mOldDatas.size() : 0;
        }
    
        //新数据集size
        @Override
        public int getNewListSize() {
            return mNewDatas != null ? mNewDatas.size() : 0;
        }
    
        /**
         * Called by the DiffUtil to decide whether two object represent the same Item.
         * 被DiffUtil调用,用来判断 两个对象是否是相同的Item。
         * For example, if your items have unique ids, this method should check their id equality.
         * 例如,如果你的Item有唯一的id字段,这个方法就 判断id是否相等。
         * 本例判断name字段是否一致
         *
         *  来了一个或一堆数据来和当前的item比较是否是新的数据,
         *      如果是新的数据就返回false,不再调用(areContentsTheSame和getChangePayload)
         *      一样数据返回true,并调用areContentsTheSame
         *
         * @param oldItemPosition The position of the item in the old list
         * @param newItemPosition The position of the item in the new list
         * @return True if the two items represent the same object or false if they are different.
         */
        @Override
        public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
            return mOldDatas.get(oldItemPosition).getName().equals(mNewDatas.get(newItemPosition).getName());
        }
    
        /**
         * 在areItemsTheSame()返回true时,已经唯一标示一样了,那么就会调用这个方法,来判断是否内容有新的更新了;
         *          如果返回false说明item数据有新的变化了, 并调用getChangePayload
         *          如果返回true唯一标示没有变化(areItemsTheSame为true) 并且内容还是一样的,说明这个item没有新个更新,数据不刷新
         *
         * Called by the DiffUtil when it wants to check whether two items have the same data.
         * 被DiffUtil调用,用来检查 两个item是否含有相同的数据
         * DiffUtil uses this information to detect if the contents of an item has changed.
         * DiffUtil用返回的信息(true false)来检测当前item的内容是否发生了变化
         * DiffUtil uses this method to check equality instead of {@link Object#equals(Object)}
         * DiffUtil 用这个方法替代equals方法去检查是否相等。
         * so that you can change its behavior depending on your UI.
         * 所以你可以根据你的UI去改变它的返回值
         * For example, if you are using DiffUtil with a
         * {@link android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, you should
         * return whether the items' visual representations are the same.
         * 例如,如果你用RecyclerView.Adapter 配合DiffUtil使用,你需要返回Item的视觉表现是否相同。
         * This method is called only if {@link #areItemsTheSame(int, int)} returns
         * {@code true} for these items.
         * 这个方法仅仅在areItemsTheSame()返回true时,才调用。
         *
         * @param oldItemPosition The position of the item in the old list
         * @param newItemPosition The position of the item in the new list which replaces the
         *                        oldItem
         * @return True if the contents of the items are the same or false if they are different.
         */
        @Override
        public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
            TestBean beanOld = mOldDatas.get(oldItemPosition);
            TestBean beanNew = mNewDatas.get(newItemPosition);
            if (!beanOld.getDesc().equals(beanNew.getDesc())) {
                return false;//如果有内容不同,就返回false
            }
            if (beanOld.getPic() != beanNew.getPic()) {
                return false;//如果有内容不同,就返回false
            }
            return true; //默认两个data内容是相同的
        }
    
        /**
         * When {@link #areItemsTheSame(int, int)} returns {@code true} for two items and
         * {@link #areContentsTheSame(int, int)} returns false for them, DiffUtil
         * calls this method to get a payload about the change.
         * <p>
         * 当{@link #areItemsTheSame(int, int)} 返回true,且{@link #areContentsTheSame(int, int)} 返回false时,DiffUtils会回调此方法,
         * 去得到这个Item(有哪些)改变的payload。
         * <p>
         * For example, if you are using DiffUtil with {@link RecyclerView}, you can return the
         * particular field that changed in the item and your
         * {@link android.support.v7.widget.RecyclerView.ItemAnimator ItemAnimator} can use that
         * information to run the correct animation.
         * <p>
         * 例如,如果你用RecyclerView配合DiffUtils,你可以返回  这个Item改变的那些字段,
         * {@link android.support.v7.widget.RecyclerView.ItemAnimator ItemAnimator} 可以用那些信息去执行正确的动画
         * <p>
         * Default implementation returns {@code null}.\
         * 默认的实现是返回null
         *
         * @param oldItemPosition The position of the item in the old list
         * @param newItemPosition The position of the item in the new list
         * @return A payload object that represents the change between the two items.
         * 返回 一个 代表着新老item的改变内容的 payload对象,
         */
        @Nullable
        @Override
        public Object getChangePayload(int oldItemPosition, int newItemPosition) {
            //实现这个方法 就能成为文艺青年中的文艺青年
            // 定向刷新中的部分更新
            // 效率最高
            //只是没有了ItemChange的白光一闪动画,(反正我也觉得不太重要)
            TestBean oldBean = mOldDatas.get(oldItemPosition);
            TestBean newBean = mNewDatas.get(newItemPosition);
    
            //这里就不用比较核心字段了,一定相等
            Bundle payload = new Bundle();
            if (!oldBean.getDesc().equals(newBean.getDesc())) {
                payload.putString("KEY_DESC", newBean.getDesc());
            }
            if (oldBean.getPic() != newBean.getPic()) {
                payload.putInt("KEY_PIC", newBean.getPic());
            }
    
            if (payload.size() == 0)//如果没有变化 就传空
                return null;
            return payload;//
        }
    }
    
    

    getChangePayload() 设置完,在执行的时候默认就回调onBindViewHolder()返方法了

     @Override
        public void onBindViewHolder(DiffVH holder, int position, List<Object> payloads) {
            if (payloads.isEmpty()) {
                onBindViewHolder(holder, position);
            } else {
                //文艺青年中的文青
                Bundle payload = (Bundle) payloads.get(0);//取出我们在getChangePayload()方法返回的bundle
                TestBean bean = mDatas.get(position);//取出新数据源,(可以不用)
                /**
                 * 有几个item改变就会走几次(else)这个方法里
                 * 05-03 22:48:01.168 19214-19214/com.mcxtzhang.diffutils I/System.out: bean.getDesc()=Android+position==0
                 05-03 22:48:01.168 19214-19214/com.mcxtzhang.diffutils I/System.out: bean.getDesc()=android++position==1
                 */
                System.out.println("bean.getDesc()="+bean.getDesc()+"position=="+position);
                for (String key : payload.keySet()) {
                    switch (key) {
                        case "KEY_DESC":
                            //这里可以用payload里的数据,不过data也是新的 也可以用
                            holder.tv2.setText(bean.getDesc());
                            break;
                        case "KEY_PIC":
                            holder.iv.setImageResource(payload.getInt(key));
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    

    番外篇介绍 :

    public class TestBean implements Cloneable {
       private String name;
       private String desc;
       private int pic;
    
       public TestBean(String name, String desc, int pic) {
           this.name = name;
           this.desc = desc;
           this.pic = pic;
       }
    
       public int getPic() {
           return pic;
       }
    
       public void setPic(int pic) {
           this.pic = pic;
       }
    
       public String getName() {
           return name;
       }
    
       public void setName(String name) {
           this.name = name;
       }
    
       public String getDesc() {
           return desc;
       }
    
       public void setDesc(String desc) {
           this.desc = desc;
       }
    
       //仅写DEMO 用 实现克隆方法
       @Override
       public TestBean clone() throws CloneNotSupportedException {
           TestBean bean = null;
           try {
               bean = (TestBean) super.clone();
           } catch (CloneNotSupportedException e) {
               e.printStackTrace();
           }
           return bean;
       }
    }
    

    这个clone() 方法 能得到一样数据的对象,但是不是同一个地址值的对象(生成的不是一个对象,俗称浅拷贝)

    View.post()

     Log.d(TAG, "onCreate: "+isInMainThread());
            mRv.post(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "run: "+isInMainThread()+"==="+Thread.currentThread().getName());
                    mRv.post(new Runnable() {
                        @Override
                        public void run() {
                            Log.d(TAG, "run++++: "+isInMainThread()+"++++"+Thread.currentThread().getName());
                        }
                    });
                }
            });
    

    结果

     onCreate: true
    run: true===main
    run++++: true++++main
    

    post这个方法是会切换到主线程的;

    相关文章

      网友评论

          本文标题:diffutil 的方法介绍

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