Source code
package android.support.v7.widget;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.LongSparseArray;
import android.support.v4.util.Pools.Pool;
import android.support.v4.util.Pools.SimplePool;
import android.support.v7.widget.RecyclerView.ItemAnimator.ItemHolderInfo;
import android.support.v7.widget.RecyclerView.ViewHolder;
class ViewInfoStore {
private static final boolean DEBUG = false;
final ArrayMap<ViewHolder, InfoRecord> mLayoutHolderMap = new ArrayMap();
final LongSparseArray<ViewHolder> mOldChangedHolders = new LongSparseArray();
static class InfoRecord {
static final int FLAG_APPEAR = 2;
static final int FLAG_APPEAR_AND_DISAPPEAR = 3;
static final int FLAG_APPEAR_PRE_AND_POST = 14;
static final int FLAG_DISAPPEARED = 1;
static final int FLAG_POST = 8;
static final int FLAG_PRE = 4;
static final int FLAG_PRE_AND_POST = 12;
static Pool<InfoRecord> sPool = new SimplePool(20);
int flags;
@Nullable
ItemHolderInfo postInfo;
@Nullable
ItemHolderInfo preInfo;
private InfoRecord() {
}
static InfoRecord obtain() {
InfoRecord infoRecord = (InfoRecord) sPool.acquire();
return infoRecord == null ? new InfoRecord() : infoRecord;
}
static void recycle(InfoRecord record) {
record.flags = 0;
record.preInfo = null;
record.postInfo = null;
sPool.release(record);
}
static void drainCache() {
do {
} while (sPool.acquire() != null);
}
}
interface ProcessCallback {
void processAppeared(ViewHolder viewHolder, @Nullable ItemHolderInfo itemHolderInfo, ItemHolderInfo itemHolderInfo2);
void processDisappeared(ViewHolder viewHolder, ItemHolderInfo itemHolderInfo, @Nullable ItemHolderInfo itemHolderInfo2);
void processPersistent(ViewHolder viewHolder, @NonNull ItemHolderInfo itemHolderInfo, @NonNull ItemHolderInfo itemHolderInfo2);
void unused(ViewHolder viewHolder);
}
ViewInfoStore() {
}
void clear() {
this.mLayoutHolderMap.clear();
this.mOldChangedHolders.clear();
}
void addToPreLayout(ViewHolder holder, ItemHolderInfo info) {
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.get(holder);
if (record == null) {
record = InfoRecord.obtain();
this.mLayoutHolderMap.put(holder, record);
}
record.preInfo = info;
record.flags |= 4;
}
@Nullable
ItemHolderInfo popFromPreLayout(ViewHolder vh) {
ItemHolderInfo itemHolderInfo = null;
int index = this.mLayoutHolderMap.indexOfKey(vh);
if (index >= 0) {
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.valueAt(index);
if (!(record == null || (record.flags & 4) == 0)) {
record.flags &= -5;
itemHolderInfo = record.preInfo;
if (record.flags == 0) {
this.mLayoutHolderMap.removeAt(index);
InfoRecord.recycle(record);
}
}
}
return itemHolderInfo;
}
void addToOldChangeHolders(long key, ViewHolder holder) {
this.mOldChangedHolders.put(key, holder);
}
void addToAppearedInPreLayoutHolders(ViewHolder holder, ItemHolderInfo info) {
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.get(holder);
if (record == null) {
record = InfoRecord.obtain();
this.mLayoutHolderMap.put(holder, record);
}
record.flags |= 2;
record.preInfo = info;
}
boolean isInPreLayout(ViewHolder viewHolder) {
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.get(viewHolder);
return (record == null || (record.flags & 4) == 0) ? false : true;
}
ViewHolder getFromOldChangeHolders(long key) {
return (ViewHolder) this.mOldChangedHolders.get(key);
}
void addToPostLayout(ViewHolder holder, ItemHolderInfo info) {
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.get(holder);
if (record == null) {
record = InfoRecord.obtain();
this.mLayoutHolderMap.put(holder, record);
}
record.postInfo = info;
record.flags |= 8;
}
void addToDisappearedInLayout(ViewHolder holder) {
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.get(holder);
if (record == null) {
record = InfoRecord.obtain();
this.mLayoutHolderMap.put(holder, record);
}
record.flags |= 1;
}
void removeFromDisappearedInLayout(ViewHolder holder) {
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.get(holder);
if (record != null) {
record.flags &= -2;
}
}
void process(ProcessCallback callback) {
for (int index = this.mLayoutHolderMap.size() - 1; index >= 0; index--) {
ViewHolder viewHolder = (ViewHolder) this.mLayoutHolderMap.keyAt(index);
InfoRecord record = (InfoRecord) this.mLayoutHolderMap.removeAt(index);
if ((record.flags & 3) == 3) {
callback.unused(viewHolder);
} else if ((record.flags & 1) != 0) {
callback.processDisappeared(viewHolder, record.preInfo, record.postInfo);
} else if ((record.flags & 14) == 14) {
callback.processAppeared(viewHolder, record.preInfo, record.postInfo);
} else if ((record.flags & 12) == 12) {
callback.processPersistent(viewHolder, record.preInfo, record.postInfo);
} else if ((record.flags & 4) != 0) {
callback.processDisappeared(viewHolder, record.preInfo, null);
} else if ((record.flags & 8) != 0) {
callback.processAppeared(viewHolder, record.preInfo, record.postInfo);
} else if ((record.flags & 2) != 0) {
}
InfoRecord.recycle(record);
}
}
void removeViewHolder(ViewHolder holder) {
for (int i = this.mOldChangedHolders.size() - 1; i >= 0; i--) {
if (holder == this.mOldChangedHolders.valueAt(i)) {
this.mOldChangedHolders.removeAt(i);
break;
}
}
InfoRecord info = (InfoRecord) this.mLayoutHolderMap.remove(holder);
if (info != null) {
InfoRecord.recycle(info);
}
}
void onDetach() {
InfoRecord.drainCache();
}
}