In Android, listView/RecyclerView is the most commonly used UI control. The most common interaction is the refresh of list. The interaction between refresh and load involves the refresh of Adapter — notifyDataSetChanged() global refresh But notifychaged has some unavoidable drawbacks: 1. Animation that does not trigger a partial update of RecyclerView. 2. Low performance, will refresh the whole RecyclerView visible area. Previously, Google published an Api called DiffUtil that partially refreshed items in a list

DiffUtil perfectly solves the problem of global flush; Improved efficiency and performance of UI and data interaction. The following is a brief introduction to DiffUtil: It mainly involves two classes: DiffUtil.Callback: it is specifically used to define the rules of data set alignment. DiffUtil.DiffResult: The difference result returned after comparing data sets.

1. Diffutil. Callback(Comparing old and new data)

In Callback, only four methods need to be implemented:

GetOldListSize () : The length of the old dataset. GetNewListSize () : the length of the new data set areItemsTheSame() : Checks if it is the same Item. AreContentsTheSame () : This method is used to determine whether the contents of the same Item are the same.

The first two are ways to get the length of the data set, which is nothing to say. But the latter two methods were created primarily to correspond to the case of multiple layouts, that is, multiple viewTypes and multiple Viewhodlers. You first need to use the areItemsTheSame() method to check whether the contents are from the same viewType (that is, the same ViewHolder), and then use the areContentsTheSame() method to check whether the contents are also equal.

The Callback also has a getChangePayload() method, which can record the View payLoad that needs to be updated in the ViewHolder if the ViewType is the same but the content is different.

AreItemsTheSame (), areContentsTheSame(), and getChangePayload() represent different levels of refresh.

AreItemsTheSame () is used to determine whether the ViewType of the current position is consistent. If the ViewType is inconsistent, it indicates that the current position has changed from the data to the UI structure. The areContentsTheSame() method is used to determine whether the content of the View is consistent. If the content is consistent, it means that it is the same data and no additional operations are required. However, in case of inconsistency, getChangePayload() is also called to mark where the difference is, and finally to mark where it needs to be updated, which is returned to DiffResult.

Of course, you can skip the getChangedPayload() method if the performance requirements are not that high.

2.DiffUtil.DiffResult(attribute Adapter used with RecyclerView)

Through diffUtil. Callback to calculate the difference and then directly scope RecyclerView adapter refresh

3 Code Implementation

First, a RecyDiffCallback(inherited from DiffUtil.callback) encapsulates itself.

package com.example.diffutil.widget;

import android.support.v7.util.DiffUtil;

import java.util.List;

/** * Created by houruixiang on 2017/8/21. */

public class RecyDiffCallback extends DiffUtil.Callback {

    private List<String> newList;
    private List<String> oldList;

    public RecyDiffCallback(List<String> oldList, List<String> newList) {
        this.oldList = oldList;
        this.newList = newList;
    }

    @Override
    public int getOldListSize() {
        return oldList.size();
    }

    @Override
    public int getNewListSize() {
        return newList.size();
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        return oldList.get(oldItemPosition).getClass().equals(newList.get(newItemPosition).getClass());
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        String oldStr = oldList.get(oldItemPosition);
        String newStr = newList.get(newItemPosition);
        returnoldStr.equals(newStr); }}Copy the code

The above code is self-encapsulated, passing in the old and new data in the construction, and then comparing the length of the data, and then comparing whether the type of the item is the same; Finally, compare the content; Here’s the core code in MainActivity

@Override
    public void onClick(View view) {
        mOld = mData.get(index);
        index+ +;index = index % mData.size();
        mNew = mData.get(index);
        Log.i("==onClick",String.valueOf(index));
        recyAdapter.setData(mData.get(index));
        DiffUtil.DiffResult diffResult = DiffUtil
                .calculateDiff(new RecyDiffCallback(mOld, mNew),true);

        diffResult.dispatchUpdatesTo(recyAdapter);

        //mList.setAdapter(recyAdapter);

    }Copy the code
SetData into adapter in codeCopy the code
recyAdapter.setData(mData.get(index));Copy the code
Then compare the old and new dataCopy the code
  DiffUtil.DiffResult diffResult = DiffUtil
                .calculateDiff(new RecyDiffCallback(mOld, mNew),true);Copy the code

Compare old and new data sets, if triple (described above), and then perform a local refresh of diff:

diffResult.dispatchUpdatesTo(recyAdapter);Copy the code

Here RecyClerView+DiffUtil local refresh is introduced is not used to fly up; We hope for common progress and welcome your valuable opinions.