Android——RecyclerView入門學(xué)習(xí)之DiffUtil(四)

學(xué)習(xí)資料:

十分感謝 :)

DiffUtilandroid.support:design:24.2.0中推出的一個(gè)RecyclerView的輔助工具類

作用:
當(dāng)Adapter中的數(shù)據(jù)發(fā)生變化時(shí)派继,用來比較Adpater中變化前和后兩個(gè)數(shù)據(jù)集合恩急,實(shí)現(xiàn)差異化更新拌蜘。而兩個(gè)集合的整個(gè)比較過程烤芦,以及針對(duì)數(shù)據(jù)變化該調(diào)用哪些notifyData方法举娩,內(nèi)部會(huì)自動(dòng)進(jìn)行處理


1.簡(jiǎn)單使用 <p>

使用的步驟:

  1. 創(chuàng)建一個(gè)DiffUtilCallback繼承DiffUtil.Callback,重寫里面的抽象方法
  2. 使用DiffUtil.calculateDiff(callback)构罗,計(jì)算差異結(jié)果铜涉,需要DiffUtilCallback,返回對(duì)象為DiffUtil.DiffResult遂唧。
  3. 使用DiffResult對(duì)象芙代,通過diffResult.dispatchUpdatesTo(adapter)方法,將DiffUtilAdapter關(guān)聯(lián)起來

大致的思路就是這個(gè)樣子盖彭,基本也是死套路


效果:

改變?nèi)繉W(xué)科纹烹,并在加入一條

點(diǎn)擊RecyclerView的一個(gè)item,將學(xué)科全部改變召边,并在postion2處铺呵,加入一個(gè)item


1.1 創(chuàng)建DiffUtilCallback

直接繼承DiffUtil.Callback,之后Anddroid Studio便會(huì)自動(dòng)提示必須要重寫4個(gè)的方法

class DiffUtilCallback extends DiffUtil.Callback {

    private List<ResourceBean> oldList = new ArrayList<>();
    private List<ResourceBean> newList = new ArrayList<>();

    public void setNewList(List<ResourceBean> newList) {
        if (null != newList) {
            this.newList.clear();
            this.newList.addAll(newList);
        }
    }

    public void setOldList(List<ResourceBean> oldList) {
        if (null != oldList) {
            this.oldList.clear();
            this.oldList.addAll(oldList);
        }
    }

    /**
     * 數(shù)據(jù)變化之前隧熙,舊的數(shù)據(jù)集合size
     */
    @Override
    public int getOldListSize() {
        Log.e("oldList.size", "---->" + oldList.size());
        return oldList.size();
    }

    /**
     * 數(shù)據(jù)變化之后片挂,新的數(shù)據(jù)集合size
     */
    @Override
    public int getNewListSize() {
        Log.e("newList.size", "---->" + newList.size());
        return newList.size();
    }

    /**
     * 根據(jù)position來對(duì)新舊集合中的Object進(jìn)行判斷
     */
    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        ResourceBean oldBean = oldList.get(oldItemPosition);
        ResourceBean newBean = newList.get(newItemPosition);
        Log.e("areItemsTheSame", oldItemPosition + "--" + newItemPosition + "---->" + oldBean.getSubject().equals(newBean.getSubject()));
        return oldBean.getSubject().equals(newBean.getSubject());//比較科目
    }

    /**
     * 根據(jù)position來對(duì)新舊集合中的Object的內(nèi)容進(jìn)行判斷
     */
    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        ResourceBean oldBean = oldList.get(oldItemPosition);
        ResourceBean newBean = newList.get(newItemPosition);
        Log.e("areContentsTheSame", oldItemPosition + "--" + newItemPosition + "---->" + oldBean.getName().equals(newBean.getName()));
        return oldBean.getName().equals(newBean.getName());//比較學(xué)科
    }

    /**
     * 返回的特定的差異化結(jié)果
     */
    @Nullable
    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        ResourceBean oldBean = oldList.get(oldItemPosition);
        ResourceBean newBean = newList.get(newItemPosition);
        Bundle diffBundle = new Bundle();
        if (!oldBean.getName().equals(newBean.getName())) {
            diffBundle.putSerializable("newBean",newBean);
        }
        return diffBundle;
    }
}

ResourceBean內(nèi)只有兩個(gè)String類型的subject,nameset贞盯,get方法宴卖,不再給出


1.2 Adapter代碼

適配器就是一個(gè)一般寫法的適配滋将,代碼比較簡(jiǎn)單

class PayloadAdapter extends RecyclerView.Adapter<PayloadAdapter.RecyclerHolder> {
    private Context mContext;
    private List<ResourceBean> dataList = new ArrayList<>();
    private onRecyclerItemClickerListener mListener;

    public PayloadAdapter(RecyclerView recyclerView) {
        this.mContext = recyclerView.getContext();
    }


    /**
     * 增加點(diǎn)擊監(jiān)聽
     */
    public void setItemListener(onRecyclerItemClickerListener mListener) {
        this.mListener = mListener;
    }

    /**
     * 設(shè)置數(shù)據(jù)源
     */
    public void setData(List<ResourceBean> dataList) {
        if (null != dataList) {
            this.dataList.clear();
            this.dataList.addAll(dataList);
        }
    }

    public List<ResourceBean> getDataList() {
        return dataList;
    }

    @Override
    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout, parent, false);
        return new RecyclerHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position) {
        ResourceBean resourceBean = dataList.get(position);
        holder.textView.setText(resourceBean.getSubject() + "--->" + resourceBean.getName());
        holder.textView.setOnClickListener(getOnClickListener(position));
    }

    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position, List<Object> payloads) {
        super.onBindViewHolder(holder, position, payloads);
        if (payloads.isEmpty()) {
            Log.e("isEmpty", "---->" + payloads.isEmpty());
            onBindViewHolder(holder, position);
        }else {
            Log.e("isEmpty", "---->no null");
            Bundle bundle = (Bundle) payloads.get(0);
            ResourceBean resourceBean = (ResourceBean) bundle.get("newBean");
            if (null == resourceBean) return;
            // Log.e("change", "---->" + change);
            holder.textView.setText(resourceBean.getSubject() + "--->" + resourceBean.getName());
        }
    }


    private View.OnClickListener getOnClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mListener && null != v) {
                    mListener.onRecyclerItemClick(v, dataList.get(position), position);
                }
            }
        };
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    class RecyclerHolder extends RecyclerView.ViewHolder {
        TextView textView;

        private RecyclerHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv__id_item_layout);
        }
    }

    /**
     * 點(diǎn)擊監(jiān)聽回調(diào)接口
     */
    public interface onRecyclerItemClickerListener {
        void onRecyclerItemClick(View view, Object data, int position);
    }
}

加入了一個(gè)onBindViewHolder(RecyclerHolder holder, int position, List<Object> payloads)方法


1.3 與Adapter進(jìn)行關(guān)聯(lián) <p>

在創(chuàng)建Adapter的Activity中,完整代碼:

 class DiffUtil2Activity extends AppCompatActivity {
    private RecyclerView rv;
    private PayloadAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_diff_util2);
        init();
    }

    private void init() {
        rv = (RecyclerView) findViewById(R.id.rv_diff2_util_activity);
        //布局管理器
        LinearLayoutManager manager = new LinearLayoutManager(this);
        manager.setOrientation(LinearLayoutManager.VERTICAL);
        rv.setLayoutManager(manager);
        //設(shè)置ItemDecoration
        rv.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
        //適配器
        mAdapter = new PayloadAdapter(rv);
        rv.setAdapter(mAdapter);
        //添加數(shù)據(jù)
        addData();
    }

    private void addData() {
        DiffUtilCallback callback = new DiffUtilCallback();
        callback.setOldList(mAdapter.getDataList());
        List<ResourceBean> oldList = new ArrayList<>();
        for (int i = 'A'; i < 'D'; i++) {
            for (int j = 0; j < 15; j++) {
                ResourceBean resourceBean = new ResourceBean();
                resourceBean.setSubject("學(xué)科" + (char) i);
                resourceBean.setName("資料" + j);
                oldList.add(resourceBean);
            }
        }
        callback.setNewList(oldList);
        DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);//子線程計(jì)算差異
        diffResult.dispatchUpdatesTo(mAdapter);
        //記得將新數(shù)據(jù)替換adapter中舊的集合數(shù)據(jù)
        mAdapter.setData(oldList);
        //設(shè)置點(diǎn)擊事件
        mAdapter.setItemListener(new PayloadAdapter.onRecyclerItemClickerListener() {
            @Override
            public void onRecyclerItemClick(View view, Object data, int position) {
                changeData();
            }
        });
    }

    private void changeData() {
        DiffUtilCallback callback = new DiffUtilCallback();
        callback.setOldList(mAdapter.getDataList());
        List<ResourceBean> newList = new ArrayList<>();
        for (int i = 'A'; i < 'D'; i++) {
            for (int j = 0; j < 15; j++) {
                ResourceBean resourceBean = new ResourceBean();
                resourceBean.setSubject("學(xué)科" + (char) i);
                resourceBean.setName("吃飯課" + j);
                newList.add(resourceBean);
            }
        }
        ResourceBean r = new ResourceBean();
        r.setSubject("體育課");
        r.setName("---->666666");
        newList.add(4, r);
        callback.setNewList(newList);
        //這是主線程症昏。下面有案例放在了子線程中
        DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);//子線程計(jì)算差異 
        diffResult.dispatchUpdatesTo(mAdapter);
        mAdapter.setData(newList);
    }
     @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != rv) rv.setAdapter(null);
    }
}

而關(guān)聯(lián)操作關(guān)鍵的代碼也就2

DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);
diffResult.dispatchUpdatesTo(adapter);//與Adapter進(jìn)行關(guān)聯(lián)

這時(shí)計(jì)算兩個(gè)List的過程是放在UI主線程到了實(shí)際開發(fā)中父丰,數(shù)據(jù)量往往會(huì)比較大肝谭,計(jì)算差異化這一步,最好做些處理放在一個(gè)子線程中

在上一篇RecyclerView.Adapter學(xué)習(xí)的1.5小節(jié)一系列的notifyData方法中蛾扇,移除或者增加同類型對(duì)象的item時(shí)攘烛,說會(huì)感覺卡頓,使用DiffUtil感覺好多了镀首,可能心理作用坟漱。。更哄。

如果只是想做個(gè)芋齿,感覺沒必要使用DiffUtilRecycelrView.Adapter提供的局部刷新感覺蠻好用的了成翩。有一個(gè)特別適合使用的場(chǎng)景便是下拉刷新觅捆,不僅有動(dòng)畫,效率也有提高麻敌,尤其是下拉刷新操作后栅炒,Adapter內(nèi)集合數(shù)據(jù)并沒有發(fā)生改變,不需要進(jìn)行重新繪制RecyclerView時(shí)


2. DiffUtil <p>

DiffUtil.DiffResultDiffUtil.CallbackDiffUtil的兩個(gè)內(nèi)部類术羔。DiffUtil對(duì)外提供的public方法只有2個(gè)

方法1:

 /**
  * Calculates the list of update operations that can covert one list into the other one.
  *
  * @param cb The callback that acts as a gateway to the backing list data
  *
  * @return A DiffResult that contains the information about the edit sequence to convert the old list into the new list.
  */
public static DiffResult calculateDiff(Callback cb) {
    return calculateDiff(cb, true);
}

這個(gè)方法用于計(jì)算newListoldList的差異赢赊,在內(nèi)部計(jì)算出后的操作便是將兩個(gè)列表轉(zhuǎn)換成為另一個(gè)新的集合,但轉(zhuǎn)換過程并不用再操心的

在方法內(nèi)级历,調(diào)用了兩個(gè)參數(shù)的calculateDiff(cb, true)释移,便是方法2


方法2:

/**
 * Calculates the list of update operations that can covert one list into the other one.
 * <p>
 * If your old and new lists are sorted by the same constraint and items never move (swap positions), you can disable move detection which takes <code>O(N^2)</code> time where N is the number of added, moved, removed items.
 *
 * @param cb The callback that acts as a gateway to the backing list data
 * @param detectMoves True if DiffUtil should try to detect moved items, false otherwise.
 *
 * @return A DiffResult that contains the information about the edit sequence to convert the old list into the new list.
 */
public static DiffResult calculateDiff(Callback cb, boolean detectMoves) {
   ...

   //做過修改的Eugene W. Myers’s difference算法
   final Snake snake = diffPartial(cb, range.oldListStart, range.oldListEnd, range.newListStart, range.newListEnd, forward, backward, max);
   
   ...
   
   return new DiffResult(cb, snakes, forward, backward, detectMoves);
  • boolean detectMoves:是否檢測(cè)item是否移動(dòng),使用方法1默認(rèn)為ture鱼喉,這樣相對(duì)fasle也會(huì)耗時(shí)一些

具體哪種場(chǎng)景下設(shè)置為false秀鞭,目前還不了解,有知道的同學(xué)請(qǐng)留言告訴一聲

在這個(gè)方法中扛禽,calculateDiff()算是整個(gè)DiffUtil的核心操作锋边,計(jì)算差異化操作,里面涉及到的算法以后再進(jìn)行學(xué)習(xí)

最后返回了一個(gè)DiffResult對(duì)象编曼,這個(gè)對(duì)象內(nèi)部封裝著進(jìn)行了差異化比較操作后的轉(zhuǎn)換的數(shù)據(jù)集合豆巨。這個(gè)對(duì)象內(nèi)部涉及到的轉(zhuǎn)換操作,暫時(shí)也不打算進(jìn)行學(xué)習(xí)掐场,等對(duì)于DiffUtil的使用相對(duì)熟練一些后往扔,再進(jìn)行學(xué)習(xí)


2.1 DiffUtil.Callback <p>

在這個(gè)抽象類中贩猎,一共有5個(gè)抽象方法:

方法 作用
public abstract int getOldListSize() 新集合的size
public abstract int getNewListSize() 舊集合的size
public abstract boolean areItemsTheSame() 判斷兩個(gè)集合中Object是否相同
public abstract boolean areContentsTheSame() 檢查兩個(gè)item的對(duì)象內(nèi)容是否相同
public Object getChangePayload() @Nullable,非必需重寫的方法萍膛,得到封裝新舊集合中兩個(gè)item負(fù)載對(duì)象吭服,默認(rèn)返回null

前兩個(gè)方法很好理解,后面3個(gè)方法需要根據(jù)源碼中的注釋來學(xué)習(xí)


2.1.1 areItemsTheSame()判斷Item中Objecct是否相同 <p>

源碼:

/**
 * Called by the DiffUtil to decide whether two object represent the same Item.
 * 進(jìn)行比較新舊集合中在oldItemPosition與newItemPosition兩個(gè)對(duì)象是否相同
 *
 * For example, if your items have unique ids, this method should check their id equality.
 *例如蝗罗,當(dāng)集合中的對(duì)象有唯一的標(biāo)記ids時(shí)艇棕,就比較兩個(gè)對(duì)象的ids
 *
 * @param oldItemPosition The position of the item in the old list
 * 對(duì)象在舊的集合中的position
 * @param newItemPosition The position of the item in the new list
 * 對(duì)象在新的集合中的position
 * @return True if the two items represent the same object or false if they are different.
 * 返回比較結(jié)果
 */
 public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);

這個(gè)方法的返回結(jié)果會(huì)對(duì)areContentsTheSame()方法有影響


2.1.2 areContentsTheSame()判斷Objecct中的內(nèi)容是否相同<p>

源碼:

 /**
  * Called by the DiffUtil when it wants to check whether two items have the same data.
  * 比較新舊集合對(duì)象中的內(nèi)容是否一樣
  * DiffUtil uses this information to detect if the contents of an item has changed.
  * DiffUtil利用這個(gè)方法的返回值來檢測(cè)一個(gè)對(duì)象是否發(fā)生變化
  * 
  * DiffUtil uses this method to check equality instead of {@link Object#equals(Object)}
  * DiffUtil使用這個(gè)方法代替equals()來檢測(cè)是否相等
  * so that you can change its behavior depending on your UI.
  * 可以根據(jù)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使用時(shí)串塑,需要返回RecycelrView的item視覺效果是否一致
  *這里視覺效果應(yīng)該指的就是動(dòng)畫吧
  *
  * This method is called only if {@link #areItemsTheSame(int, int)} returns{@code true} for these items.
  *這個(gè)方法只有在areItemsTheSame()方法返回ture時(shí)才會(huì)被調(diào)用
  * @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.
  */
public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);

只有當(dāng)areContentsTheSame()方法返回true時(shí)沼琉,這個(gè)方法才會(huì)被掉y用。不難理解桩匪,只有聽一個(gè)類型的對(duì)象才可以比較的意義


2.1.3 getChangePayload()得到封裝差異化信息的對(duì)象 <p>

源碼:

 /**
  * 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.
  * 當(dāng)areItemsTheSame()返回true并且areContentsTheSame返回false打瘪,DiffUtil便會(huì)調(diào)用這個(gè)方法將兩個(gè)item的差異封裝在一個(gè)負(fù)載對(duì)象中
  *
  * <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.
  * 例如,當(dāng)配合RecyclerView使用DiffUtil時(shí)傻昙,可以將新的item改變的特定屬性返回闺骚,還可以使用返回的差異屬性利用RecyclerView.ItemAnimator使用改變的動(dòng)畫
  *
  * <p>
  * Default implementation returns {@code null}.
  *默認(rèn)返回為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.
  */
  @Nullable
  public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        return null;
  }

使用這個(gè)方法,有特定的條件:
areItemsTheSame()返回true屋匕,areContentsTheSame返回false

這個(gè)方法還要重寫RecyclerView.AdapteronBindViewHolder(RecyclerHolder holder, int position, List<Object> payloads)

DiffUtil將返回的封裝差異化的對(duì)象存儲(chǔ)在一個(gè)List集合中葛碧,集合payloads對(duì)象不會(huì)為null,但可能會(huì)為empty过吻,也就是只有集合對(duì)象进泼,而集合中卻是空的。在onBindViewHolder()需要加判斷payloads.isEmpty()纤虽,若為empty就調(diào)用兩個(gè)參數(shù)的onBindViewHolder()


簡(jiǎn)單使用:

DiffUtilCallback中對(duì)應(yīng):

    /**
     * 返回的特定的差異化結(jié)果
     */
    @Nullable
    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        ResourceBean oldBean = oldList.get(oldItemPosition);
        ResourceBean newBean = newList.get(newItemPosition);
        Bundle diffBundle = new Bundle();
        if (!oldBean.getName().equals(newBean.getName())) {
            diffBundle.putSerializable("newBean",newBean);
        }
        return diffBundle;
    }```

**在Adapter中對(duì)應(yīng):**
```java
    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position, List<Object> payloads) {
        super.onBindViewHolder(holder, position, payloads);
        if (payloads.isEmpty()) {
            Log.e("isEmpty", "---->" + payloads.isEmpty());
            onBindViewHolder(holder, position);
        }else {
            Log.e("isEmpty", "---->no null");
            Bundle bundle = (Bundle) payloads.get(0);
            ResourceBean resourceBean = (ResourceBean) bundle.get("newBean");
            if (null == resourceBean) return;
            // Log.e("change", "---->" + change);
            holder.textView.setText(resourceBean.getSubject() + "--->" + resourceBean.getName());
        }
    }

注意要先判斷payloads中是否含有差異化數(shù)據(jù)


子線程模擬網(wǎng)絡(luò)請(qǐng)求乳绕,完整的Activity代碼:

public class DiffUtilActivity extends AppCompatActivity {

    private RecyclerView rv;
    private PayloadAdapter mAdapter;
    private StaticHandler mHandler = null;
    private static final int ADD_DATA = 2 << 5;
    private static final int CHANGE_DATA = 2 << 6;
    private List<ResourceBean> oldList;
    private List<ResourceBean> newList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_diff_util);
        init();
    }

    private void init() {
        mHandler = new StaticHandler(DiffUtilActivity.this);
        rv = (RecyclerView) findViewById(R.id.rv_diff_util_activity);
        //布局管理器
        LinearLayoutManager manager = new LinearLayoutManager(this);
        manager.setOrientation(LinearLayoutManager.VERTICAL);
        rv.setLayoutManager(manager);
        //設(shè)置ItemDecoration
        rv.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
        //適配器
        mAdapter = new PayloadAdapter(rv);
        rv.setAdapter(mAdapter);
        //設(shè)置點(diǎn)擊事件
        mAdapter.setItemListener(new PayloadAdapter.onRecyclerItemClickerListener() {
            @Override
            public void onRecyclerItemClick(View view, Object data, int position) {
                changeData();
            }
        });
        //添加數(shù)據(jù)
        addData();
    }

    public static class StaticHandler extends Handler {
        private final WeakReference<DiffUtilActivity> mWeakReference;

        private StaticHandler(DiffUtilActivity activity) {
            mWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            DiffUtilActivity activity = mWeakReference.get();
            if (null != activity) {
                PayloadAdapter adapter = activity.mAdapter;
                if (msg.what == ADD_DATA) {
                    List<ResourceBean> list = activity.oldList;
                    DiffUtil.DiffResult diffResult = (DiffUtil.DiffResult) msg.obj;
                    diffResult.dispatchUpdatesTo(adapter);
                    adapter.setData(list);
//                 adapter.notifyDataSetChanged(); //由上面代替
                } else if (msg.what == CHANGE_DATA) {
                    List<ResourceBean> newData = activity.newList;
                    DiffUtil.DiffResult diffResult = (DiffUtil.DiffResult) msg.obj;
                    diffResult.dispatchUpdatesTo(adapter);
                    adapter.setData(newData);
                }
            }
        }
    }


    /**
     * 點(diǎn)擊之后,更改數(shù)據(jù)
     */
    private void changeData() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                Message message = mHandler.obtainMessage();
                DiffUtilCallback callback = new DiffUtilCallback();
                callback.setOldList(mAdapter.getDataList());
                newList = new ArrayList<>();
                //模擬下拉刷新數(shù)據(jù)沒有變化
//                for (int i = 'A'; i < 'D'; i++) {
//                    for (int j = 0; j < 15; j++) {
//                        ResourceBean resourceBean = new ResourceBean();
//                        resourceBean.setSubject("學(xué)科" + (char) i);
//                        resourceBean.setName("資料" + j);
//                        newList.add(resourceBean);
//                    }
//                }
                for (int i = 'A'; i < 'D'; i++) {
                    for (int j = 0; j < 15; j++) {
                        ResourceBean resourceBean = new ResourceBean();
                        resourceBean.setSubject("學(xué)科" + (char) i);
                        resourceBean.setName("吃飯課" + j);
                        newList.add(resourceBean);
                    }
                }
                ResourceBean r = new ResourceBean();
                r.setSubject("體育課");
                r.setName("---->666666");
                newList.add(4, r);
                callback.setNewList(newList);
                DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);//子線程計(jì)算差異
                message.what = CHANGE_DATA;
                message.obj = diffResult;
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mHandler.sendMessage(message);
            }
        }).start();
    }

    /**
     * 第一次加入數(shù)據(jù)
     */
    private void addData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Message message = mHandler.obtainMessage();
                DiffUtilCallback callback = new DiffUtilCallback();
                callback.setOldList(mAdapter.getDataList());
                oldList = new ArrayList<>();
                for (int i = 'A'; i < 'D'; i++) {
                    for (int j = 0; j < 15; j++) {
                        ResourceBean resourceBean = new ResourceBean();
                        resourceBean.setSubject("學(xué)科" + (char) i);
                        resourceBean.setName("資料" + j);
                        oldList.add(resourceBean);
                    }
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(500);//模擬網(wǎng)絡(luò)耗時(shí)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                callback.setNewList(oldList);
                DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);//子線程計(jì)算差異
                message.what = ADD_DATA;
                message.obj = diffResult;
                mHandler.sendMessage(message);
            }
        }).start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != rv) rv.setAdapter(null);
    }
}

補(bǔ)充:

2016 12月8號(hào) 00:16 發(fā)現(xiàn)之前寫的有嚴(yán)重錯(cuò)誤逼纸,已經(jīng)修改洋措。改代碼一直到1:02,越看越感覺代碼爛杰刽,困了菠发,先睡覺,以后對(duì)DiffUtil再熟悉一點(diǎn)再來修改


3.最后 <p>

這篇學(xué)習(xí)記錄得稀里糊涂的贺嫂,希望不會(huì)坑到看博客的同學(xué)

本人很菜滓鸠,有錯(cuò)誤請(qǐng)指出

共勉 :)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市第喳,隨后出現(xiàn)的幾起案子糜俗,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悠抹,死亡現(xiàn)場(chǎng)離奇詭異珠月,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)楔敌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門啤挎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人梁丘,你說我怎么就攤上這事侵浸。” “怎么了氛谜?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)区端。 經(jīng)常有香客問我值漫,道長(zhǎng),這世上最難降的妖魔是什么织盼? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任杨何,我火速辦了婚禮,結(jié)果婚禮上沥邻,老公的妹妹穿的比我還像新娘危虱。我一直安慰自己,他們只是感情好唐全,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布埃跷。 她就那樣靜靜地躺著,像睡著了一般邮利。 火紅的嫁衣襯著肌膚如雪弥雹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天延届,我揣著相機(jī)與錄音剪勿,去河邊找鬼。 笑死方庭,一個(gè)胖子當(dāng)著我的面吹牛厕吉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播械念,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼头朱,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了订讼?” 一聲冷哼從身側(cè)響起髓窜,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后寄纵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳖敷,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年程拭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了定踱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恃鞋,死狀恐怖崖媚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情恤浪,我是刑警寧澤畅哑,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站水由,受9級(jí)特大地震影響荠呐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砂客,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一泥张、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鞠值,春花似錦媚创、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粤剧,卻和暖如春歇竟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抵恋。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工焕议, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弧关。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓盅安,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親世囊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子别瞭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容