package androidx.recyclerview.widget; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.collection.LongSparseArray; import androidx.collection.SimpleArrayMap; import androidx.core.util.Pools; import androidx.recyclerview.widget.RecyclerView; public class ViewInfoStore { private static final boolean DEBUG = false; @VisibleForTesting public final SimpleArrayMap mLayoutHolderMap = new SimpleArrayMap<>(); @VisibleForTesting public final LongSparseArray mOldChangedHolders = new LongSparseArray<>(); public static class InfoRecord { public static final int FLAG_APPEAR = 2; public static final int FLAG_APPEAR_AND_DISAPPEAR = 3; public static final int FLAG_APPEAR_PRE_AND_POST = 14; public static final int FLAG_DISAPPEARED = 1; public static final int FLAG_POST = 8; public static final int FLAG_PRE = 4; public static final int FLAG_PRE_AND_POST = 12; public static Pools.Pool sPool = new Pools.SimplePool(20); public int flags; @Nullable public RecyclerView.ItemAnimator.ItemHolderInfo postInfo; @Nullable public RecyclerView.ItemAnimator.ItemHolderInfo preInfo; private InfoRecord() { } public static void drainCache() { do { } while (sPool.acquire() != null); } public static InfoRecord obtain() { InfoRecord acquire = sPool.acquire(); return acquire == null ? new InfoRecord() : acquire; } public static void recycle(InfoRecord infoRecord) { infoRecord.flags = 0; infoRecord.preInfo = null; infoRecord.postInfo = null; sPool.release(infoRecord); } } public interface ProcessCallback { void processAppeared(RecyclerView.ViewHolder viewHolder, @Nullable RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo, RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo2); void processDisappeared(RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo, @Nullable RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo2); void processPersistent(RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo, @NonNull RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo2); void unused(RecyclerView.ViewHolder viewHolder); } private RecyclerView.ItemAnimator.ItemHolderInfo popFromLayoutStep(RecyclerView.ViewHolder viewHolder, int i) { InfoRecord valueAt; RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo; int indexOfKey = this.mLayoutHolderMap.indexOfKey(viewHolder); if (indexOfKey >= 0 && (valueAt = this.mLayoutHolderMap.valueAt(indexOfKey)) != null) { int i2 = valueAt.flags; if ((i2 & i) != 0) { int i3 = (~i) & i2; valueAt.flags = i3; if (i == 4) { itemHolderInfo = valueAt.preInfo; } else if (i == 8) { itemHolderInfo = valueAt.postInfo; } else { throw new IllegalArgumentException("Must provide flag PRE or POST"); } if ((i3 & 12) == 0) { this.mLayoutHolderMap.removeAt(indexOfKey); InfoRecord.recycle(valueAt); } return itemHolderInfo; } } return null; } public void addToAppearedInPreLayoutHolders(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo) { InfoRecord infoRecord = this.mLayoutHolderMap.get(viewHolder); if (infoRecord == null) { infoRecord = InfoRecord.obtain(); this.mLayoutHolderMap.put(viewHolder, infoRecord); } infoRecord.flags |= 2; infoRecord.preInfo = itemHolderInfo; } public void addToDisappearedInLayout(RecyclerView.ViewHolder viewHolder) { InfoRecord infoRecord = this.mLayoutHolderMap.get(viewHolder); if (infoRecord == null) { infoRecord = InfoRecord.obtain(); this.mLayoutHolderMap.put(viewHolder, infoRecord); } infoRecord.flags |= 1; } public void addToOldChangeHolders(long j, RecyclerView.ViewHolder viewHolder) { this.mOldChangedHolders.put(j, viewHolder); } public void addToPostLayout(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo) { InfoRecord infoRecord = this.mLayoutHolderMap.get(viewHolder); if (infoRecord == null) { infoRecord = InfoRecord.obtain(); this.mLayoutHolderMap.put(viewHolder, infoRecord); } infoRecord.postInfo = itemHolderInfo; infoRecord.flags |= 8; } public void addToPreLayout(RecyclerView.ViewHolder viewHolder, RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo) { InfoRecord infoRecord = this.mLayoutHolderMap.get(viewHolder); if (infoRecord == null) { infoRecord = InfoRecord.obtain(); this.mLayoutHolderMap.put(viewHolder, infoRecord); } infoRecord.preInfo = itemHolderInfo; infoRecord.flags |= 4; } public void clear() { this.mLayoutHolderMap.clear(); this.mOldChangedHolders.clear(); } public RecyclerView.ViewHolder getFromOldChangeHolders(long j) { return this.mOldChangedHolders.get(j); } public boolean isDisappearing(RecyclerView.ViewHolder viewHolder) { InfoRecord infoRecord = this.mLayoutHolderMap.get(viewHolder); return (infoRecord == null || (infoRecord.flags & 1) == 0) ? false : true; } public boolean isInPreLayout(RecyclerView.ViewHolder viewHolder) { InfoRecord infoRecord = this.mLayoutHolderMap.get(viewHolder); return (infoRecord == null || (infoRecord.flags & 4) == 0) ? false : true; } public void onDetach() { InfoRecord.drainCache(); } public void onViewDetached(RecyclerView.ViewHolder viewHolder) { removeFromDisappearedInLayout(viewHolder); } @Nullable public RecyclerView.ItemAnimator.ItemHolderInfo popFromPostLayout(RecyclerView.ViewHolder viewHolder) { return popFromLayoutStep(viewHolder, 8); } @Nullable public RecyclerView.ItemAnimator.ItemHolderInfo popFromPreLayout(RecyclerView.ViewHolder viewHolder) { return popFromLayoutStep(viewHolder, 4); } public void process(ProcessCallback processCallback) { for (int size = this.mLayoutHolderMap.size() - 1; size >= 0; size--) { RecyclerView.ViewHolder keyAt = this.mLayoutHolderMap.keyAt(size); InfoRecord removeAt = this.mLayoutHolderMap.removeAt(size); int i = removeAt.flags; if ((i & 3) == 3) { processCallback.unused(keyAt); } else if ((i & 1) != 0) { RecyclerView.ItemAnimator.ItemHolderInfo itemHolderInfo = removeAt.preInfo; if (itemHolderInfo == null) { processCallback.unused(keyAt); } else { processCallback.processDisappeared(keyAt, itemHolderInfo, removeAt.postInfo); } } else if ((i & 14) == 14) { processCallback.processAppeared(keyAt, removeAt.preInfo, removeAt.postInfo); } else if ((i & 12) == 12) { processCallback.processPersistent(keyAt, removeAt.preInfo, removeAt.postInfo); } else if ((i & 4) != 0) { processCallback.processDisappeared(keyAt, removeAt.preInfo, null); } else if ((i & 8) != 0) { processCallback.processAppeared(keyAt, removeAt.preInfo, removeAt.postInfo); } InfoRecord.recycle(removeAt); } } public void removeFromDisappearedInLayout(RecyclerView.ViewHolder viewHolder) { InfoRecord infoRecord = this.mLayoutHolderMap.get(viewHolder); if (infoRecord != null) { infoRecord.flags &= -2; } } public void removeViewHolder(RecyclerView.ViewHolder viewHolder) { int size = this.mOldChangedHolders.size() - 1; while (true) { if (size < 0) { break; } else if (viewHolder == this.mOldChangedHolders.valueAt(size)) { this.mOldChangedHolders.removeAt(size); break; } else { size--; } } InfoRecord remove = this.mLayoutHolderMap.remove(viewHolder); if (remove != null) { InfoRecord.recycle(remove); } } }