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