使用自定义添加视图(如空列表)时出现Android DiffUtil不一致异常

使用自定义添加视图(如空列表)时出现Android DiffUtil不一致异常,android,android-recyclerview,android-diffutils,Android,Android Recyclerview,Android Diffutils,我需要有关DiffUtil for RecyclerView适配器的帮助。我制作了一个自定义适配器,可以添加自定义视图,如加载视图或空视图等。没有使用DiffUtil,一切都可以正常工作,但当我使用它时,有时会检测到不一致异常。我认为问题在于getItemCount()方法,但我不确定。如果有人能给我一个建议,那将非常有帮助。这是我正在使用的代码 这是我的DiffUtil适配器类: public abstract class DiffRecyclerViewAdapter<T extend

我需要有关DiffUtil for RecyclerView适配器的帮助。我制作了一个自定义适配器,可以添加自定义视图,如加载视图或空视图等。没有使用DiffUtil,一切都可以正常工作,但当我使用它时,有时会检测到不一致异常。我认为问题在于getItemCount()方法,但我不确定。如果有人能给我一个建议,那将非常有帮助。这是我正在使用的代码

这是我的DiffUtil适配器类:

public abstract class DiffRecyclerViewAdapter<T extends DiffComparable<T>> extends BaseRecyclerViewAdapter<T> {

private DifferenceCalculator<T> mDiffCalculator = new DifferenceCalculator<>(
        new DifferenceCalculator.DiffCallback<>(getPayloadCallback()),
        new UpdateCallback(this),
        TaskExecutor.getInstance().getExecutor());

public DiffRecyclerViewAdapter(Context mContext, List<T> itemList) {
    super(mContext, itemList);
    setDataIsLoading(true);
}

public DiffRecyclerViewAdapter(Context mContext, List<T> itemList, int itemsLeftToLoadMore, LoadMoreDataCallback listener) {
    super(mContext, itemList, itemsLeftToLoadMore, listener);
    setDataIsLoading(true);
}

public void setItemList(List<T> list) {
    if (isLoading()) {
        setDataIsLoading(false, true);
    }
    mDiffCalculator.calculateDifference(list);
}

@Override
public int getItemCount() {
    int superCount = super.getItemCount();
    log("getItemCount() called with count=" + mDiffCalculator.getCurrentList().size());
    return superCount > mDiffCalculator.getCurrentList().size() ? superCount : mDiffCalculator.getCurrentList().size();
}

@Override
public List<T> getList() {
    return mDiffCalculator.getCurrentList();
}

protected abstract PayloadCallback<T> getPayloadCallback();

protected void onNewList() {
}

protected void onItemsInserted(int position, int count) {
    log("onItemsInserted(position=" + position + ", count=" + count + ")");
    notifyItemRangeInserted(position, count);
}

@SuppressWarnings("WeakerAccess")
protected void onItemsRemoved(int position, int count) {
    log("onItemsRemoved(position=" + position + ", count=" + count + ")");
    notifyItemRangeRemoved(position, count);
}

@SuppressWarnings("WeakerAccess")
protected void onItemMoved(int fromPosition, int toPosition) {
    log("onItemMoved(fromPosition=" + fromPosition + ", toPosition=" + toPosition + ")");
    notifyItemMoved(fromPosition, toPosition);
}

@SuppressWarnings("WeakerAccess")
protected void onItemsChanged(int position, int count, @Nullable Object payload) {
    log("onItemsChanged(position=" + position + ", count=" + count + ", payload=" + payload + ")");
    notifyItemRangeChanged(position, count, payload);
}

public void log(String msg) {
    if (IN_DEBUG_MODE) {
        Log.i(getClass().getSimpleName(), msg);
    }
}

public static class UpdateCallback implements ListUpdateCallback {

    private DiffRecyclerViewAdapter adapter;

    private UpdateCallback(DiffRecyclerViewAdapter adapter) {
        this.adapter = adapter;
    }

    @SuppressWarnings("WeakerAccess")
    public void onUpdateStart() {
        Log.w(getClass().getSimpleName(), "onUpdateStart()");
        adapter.setListUpdateInProgress(true);
    }

    @SuppressWarnings("WeakerAccess")
    public void onUpdateFinish() {
        Log.w(getClass().getSimpleName(), "onUpdateFinish()");
        adapter.setListUpdateInProgress(false);
    }

    @SuppressWarnings("WeakerAccess")
    public void onNewList() {
        adapter.onNewList();
    }

    @Override
    public void onInserted(int position, int count) {
        adapter.onItemsInserted(position, count);
    }

    @Override
    public void onRemoved(int position, int count) {
        adapter.onItemsRemoved(position, count);
    }

    @Override
    public void onMoved(int fromPosition, int toPosition) {
        adapter.onItemMoved(fromPosition, toPosition);
    }

    @Override
    public void onChanged(int position, int count, @Nullable Object payload) {
        adapter.onItemsChanged(position, count, payload);
    }
}

public interface PayloadCallback<T> {
    @Nullable
    Object getChangePayload(T oldItem, T newItem);
}

}
公共抽象类DiffecyclServiceAdapter扩展了BaseRecyclServiceAdapter{
专用差异计算器mDiffCalculator=新差异计算器(
新的DifferenceCalculator.DiffCallback(getPayloadCallback()),
新的UpdateCallback(此),
TaskExecutor.getInstance().getExecutor());
公共DifferCyclerServiceAdapter(上下文mContext、列表项列表){
super(mContext、itemList);
setDataIsLoading(真);
}
公共DiffercyServiceAdapter(上下文mContext、列表itemList、int itemsLeftToLoadMore、LoadMoreDataCallback侦听器){
super(mContext、itemList、itemsLeftToLoadMore、listener);
setDataIsLoading(真);
}
公共无效setItemList(列表){
if(isLoading()){
setDataIsLoading(假、真);
}
mDiffCalculator.calculateDifference(列表);
}
@凌驾
public int getItemCount(){
int superCount=super.getItemCount();
日志(“使用count=“+mdiffcaulator.getCurrentList().size())调用getItemCount());
返回超级计数>mDiffCalculator.getCurrentList().size()?超级计数:mDiffCalculator.getCurrentList().size();
}
@凌驾
公共列表getList(){
返回mDiffCalculator.getCurrentList();
}
受保护的抽象PayloadCallback getPayloadCallback();
受保护的void onNewList(){
}
已插入受保护的无效数据(整数位置,整数计数){
日志(“已插入(位置=“+position+”,计数=“+count+”));
notifyItemRangeInserted(位置、计数);
}
@抑制警告(“弱化访问”)
已删除受保护的无效项(整数位置,整数计数){
日志(“删除(位置=“+position+”,计数=“+count+”);
notifyItemRangeRemoved(位置、计数);
}
@抑制警告(“弱化访问”)
受保护的未移动空间(int-fromPosition、int-toPosition){
日志(“onItemMoved(fromPosition=“+fromPosition+”,toPosition=“+toPosition+”);
已移动的项目(从位置、位置);
}
@抑制警告(“弱化访问”)
受保护的无效数据已更改(整数位置、整数计数、@Nullable对象负载){
日志(“已更改(位置=“+position+”,计数=“+count+”,有效载荷=“+payload+”));
NotifyItemRange已更改(位置、计数、有效载荷);
}
公共无效日志(字符串msg){
如果(在调试模式下){
Log.i(getClass().getSimpleName(),msg);
}
}
公共静态类UpdateCallback实现ListUpdateCallback{
专用DiffreCyclerServiceAdapter适配器;
专用UpdateCallback(DiffreCyclerServiceAdapter适配器){
this.adapter=适配器;
}
@抑制警告(“弱化访问”)
public void onUpdateStart(){
w(getClass().getSimpleName(),“onUpdateStart()”);
setListUpdateInProgress(true);
}
@抑制警告(“弱化访问”)
public void onUpdate完成(){
w(getClass().getSimpleName(),“onUpdateFinish()”);
adapter.setListUpdateInProgress(false);
}
@抑制警告(“弱化访问”)
公共资源列表(){
adapter.onNewList();
}
@凌驾
未插入的公共无效(整数位置,整数计数){
适配器。已插入(位置、计数);
}
@凌驾
已删除公共无效(整数位置,整数计数){
适配器。已拆下(位置、计数);
}
@凌驾
移动时的公共无效(int-fromPosition,int-toPosition){
适配器。未移动(从位置、位置);
}
@凌驾
公共void onChanged(int位置、int计数、@Nullable对象负载){
适配器已更改(位置、计数、有效载荷);
}
}
公共接口PayloadCallback{
@可空
对象getChangePayload(T旧项,T新项);
}
}
这是我的差异计算器课:

public class DifferenceCalculator<T extends DiffComparable<T>> {

private MainThreadExecutor mMainThreadExecutor;
private Executor mBackgroundThreadExecutor;
private DiffCallback<T> mDiffUtilCallback;
private DiffRecyclerViewAdapter.UpdateCallback mUpdateCallback;
private List<T> mList;
private List<T> mReadOnlyList = Collections.emptyList();
private int mMaxScheduledGeneration;

@SuppressWarnings("unused")
public DifferenceCalculator(DiffCallback<T> diffCallback, DiffRecyclerViewAdapter.UpdateCallback callback) {
    this(diffCallback, callback, null);
}

@SuppressWarnings("WeakerAccess")
public DifferenceCalculator(DiffCallback<T> diffCallback,
                            DiffRecyclerViewAdapter.UpdateCallback callback,
                            Executor backgroundThreadExecutor) {
    mDiffUtilCallback = diffCallback;
    mUpdateCallback = callback;
    mMainThreadExecutor = new MainThreadExecutor();
    mBackgroundThreadExecutor = backgroundThreadExecutor != null ? backgroundThreadExecutor :
            new ThreadPoolExecutor(
                    2,
                    2,
                    30,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>()
            );
}

@SuppressWarnings("WeakerAccess")
@NonNull
public List<T> getCurrentList() {
    return mReadOnlyList;
}

@SuppressWarnings("WeakerAccess")
public void calculateDifference(@Nullable final List<T> newList) {
    final int runGeneration = ++mMaxScheduledGeneration;
    log("calculating difference for process=" + runGeneration);
    mUpdateCallback.onUpdateStart();
    if (newList == mList) {
        mUpdateCallback.onUpdateFinish();
        log("abandoned because no change!");
        return;
    }
    if (newList == null) {
        int countRemoved = mList.size();
        mList = null;
        mReadOnlyList = Collections.emptyList();
        mUpdateCallback.onRemoved(0, countRemoved);
        mUpdateCallback.onUpdateFinish();
        log("New List is null!");
        return;
    }
    if (mList == null) {
        mList = newList;
        mReadOnlyList = Collections.unmodifiableList(newList);
        mUpdateCallback.onInserted(0, newList.size());
        mUpdateCallback.onNewList();
        mUpdateCallback.onUpdateFinish();
        log("Complete new List arrived.");
        return;
    }
    final List<T> oldList = mList;
    mBackgroundThreadExecutor.execute(() -> {
        final DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
            @Override
            public int getOldListSize() {
                return oldList.size();
            }

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

            @Override
            public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
                T oldItem = oldList.get(oldItemPosition);
                T newItem = newList.get(newItemPosition);
                if (oldItem != null && newItem != null) {
                    return mDiffUtilCallback.areItemsTheSame(oldItem, newItem);
                }
                return oldItem == null && newItem == null;
            }

            @Override
            public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
                T oldItem = oldList.get(oldItemPosition);
                T newItem = newList.get(newItemPosition);
                if (oldItem != null && newItem != null) {
                    return mDiffUtilCallback.areContentsTheSame(oldItem, newItem);
                }
                if (oldItem == null && newItem == null) {
                    return true;
                }
                throw new AssertionError();
            }

            @Nullable
            @Override
            public Object getChangePayload(int oldItemPosition, int newItemPosition) {
                T oldItem = oldList.get(oldItemPosition);
                T newItem = newList.get(newItemPosition);
                if (oldItem != null && newItem != null) {
                    return mDiffUtilCallback.getChangePayload(oldItem, newItem);
                }
                throw new AssertionError();
            }
        });
        mMainThreadExecutor.execute(() -> {
            if (mMaxScheduledGeneration == runGeneration) {
                dispatchResult(newList, result);
            } else {
                mUpdateCallback.onUpdateFinish();
                log("result not dispatched because other pending calculations in queue!");
            }
        });
    });
}

private void dispatchResult(@NonNull List<T> newList, @NonNull DiffUtil.DiffResult diffResult) {
    log("dispatching result");
    mList = newList;
    mReadOnlyList = Collections.unmodifiableList(newList);
    diffResult.dispatchUpdatesTo(mUpdateCallback);
    mUpdateCallback.onUpdateFinish();
}

private static class MainThreadExecutor implements Executor {

    private Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(Runnable command) {
        handler.post(command);
    }
}

public static class DiffCallback<T extends DiffComparable<T>> {

    private DiffRecyclerViewAdapter.PayloadCallback<T> callback;

    public DiffCallback(DiffRecyclerViewAdapter.PayloadCallback<T> callback){
        this.callback = callback;
    }

    boolean areItemsTheSame(T oldItem, T newItem) {
        return oldItem.isItemTheSame(newItem);
    }

    boolean areContentsTheSame(T oldItem, T newItem) {
        return oldItem.isContentTheSame(newItem);
    }

    @Nullable
    public Object getChangePayload(T oldItem, T newItem) {
        if(callback != null){
            return callback.getChangePayload(oldItem, newItem);
        }
        return null;
    }

}

private void log(String msg){
    if(IN_DEBUG_MODE){
        Log.w(getClass().getSimpleName(), msg);
    }
}
}
公共类差异计算器{
私有MainThreadExecutor mMainThreadExecutor;
私人遗嘱执行人;
私有diffutilcallback;
private DiffecyclServiceAdapter.UpdateCallback mUpdateCallback;
私人名单;
private List mReadOnlyList=Collections.emptyList();
私有内部mMaxScheduledGeneration;
@抑制警告(“未使用”)
公共差分计算器(DiffCallback DiffCallback、DiffRecyServiceAdapter.UpdateCallback回调){
这(diffCallback,callback,null);
}
@抑制警告(“弱化访问”)
公共差分计算器(DiffCallback DiffCallback,
DifflecyServiceAdapter.UpdateCallback回调,
执行人背景(执行人){
mDiffUtilCallback=diffCallback;
mUpdateCallback=回调;
mMainThreadExecutor=新的MainThreadExecutor();
mBackgroundThreadExecutor=backgroundThreadExecutor!=null?backgroundThreadExecutor:
新线程池执行器(
2.
2.
30,
时间单位:秒,
新建LinkedBlockingQueue()
);
}
@抑制警告(“弱化访问”)
@非空
公共列表getCurrentList(){
返回mReadOnlyList;
}
@抑制警告(“弱化访问”)
public void calculateDifference(@Nullable final List newList){
最终int runGeneration=++mMaxScheduledGeneration;
日志(“计算过程差异=”+runGeneration);
mUpdateCallback.onUpdateStart();
if(newList==mList){
mUpdateCallback.onUpdateFinish();
日志(“因为没有更改而放弃!”);
回来
}
if(newList==null){
整数计数删除=
 @SuppressWarnings("WeakerAccess")
 public void onUpdateStart() {
    Log.w(getClass().getSimpleName(), "onUpdateStart()");
    adapter.setListUpdateInProgress(true);
    if(adapter.isEmptyViewVisible()){
         adapter.notifyItemChanged(0);
    }
  }