364 lines
14 KiB
Java
364 lines
14 KiB
Java
package androidx.recyclerview.widget;
|
|
|
|
import android.util.Log;
|
|
import android.util.SparseBooleanArray;
|
|
import android.util.SparseIntArray;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.UiThread;
|
|
import androidx.annotation.WorkerThread;
|
|
import androidx.recyclerview.widget.ThreadUtil;
|
|
import androidx.recyclerview.widget.TileList;
|
|
import c.d.b.a.a;
|
|
public class AsyncListUtil<T> {
|
|
public static final boolean DEBUG = false;
|
|
public static final String TAG = "AsyncListUtil";
|
|
public boolean mAllowScrollHints;
|
|
private final ThreadUtil.BackgroundCallback<T> mBackgroundCallback;
|
|
public final ThreadUtil.BackgroundCallback<T> mBackgroundProxy;
|
|
public final DataCallback<T> mDataCallback;
|
|
public int mDisplayedGeneration = 0;
|
|
public int mItemCount = 0;
|
|
private final ThreadUtil.MainThreadCallback<T> mMainThreadCallback;
|
|
public final ThreadUtil.MainThreadCallback<T> mMainThreadProxy;
|
|
public final SparseIntArray mMissingPositions = new SparseIntArray();
|
|
public final int[] mPrevRange = new int[2];
|
|
public int mRequestedGeneration = 0;
|
|
private int mScrollHint = 0;
|
|
public final Class<T> mTClass;
|
|
public final TileList<T> mTileList;
|
|
public final int mTileSize;
|
|
public final int[] mTmpRange = new int[2];
|
|
public final int[] mTmpRangeExtended = new int[2];
|
|
public final ViewCallback mViewCallback;
|
|
|
|
/* renamed from: androidx.recyclerview.widget.AsyncListUtil$1 reason: invalid class name */
|
|
public class AnonymousClass1 implements ThreadUtil.MainThreadCallback<T> {
|
|
public AnonymousClass1() {
|
|
}
|
|
|
|
private boolean isRequestedGeneration(int i) {
|
|
return i == AsyncListUtil.this.mRequestedGeneration;
|
|
}
|
|
|
|
private void recycleAllTiles() {
|
|
for (int i = 0; i < AsyncListUtil.this.mTileList.size(); i++) {
|
|
AsyncListUtil asyncListUtil = AsyncListUtil.this;
|
|
asyncListUtil.mBackgroundProxy.recycleTile(asyncListUtil.mTileList.getAtIndex(i));
|
|
}
|
|
AsyncListUtil.this.mTileList.clear();
|
|
}
|
|
|
|
@Override // androidx.recyclerview.widget.ThreadUtil.MainThreadCallback
|
|
public void addTile(int i, TileList.Tile<T> tile) {
|
|
if (!isRequestedGeneration(i)) {
|
|
AsyncListUtil.this.mBackgroundProxy.recycleTile(tile);
|
|
return;
|
|
}
|
|
TileList.Tile<T> addOrReplace = AsyncListUtil.this.mTileList.addOrReplace(tile);
|
|
if (addOrReplace != null) {
|
|
StringBuilder K = a.K("duplicate tile @");
|
|
K.append(addOrReplace.mStartPosition);
|
|
Log.e("AsyncListUtil", K.toString());
|
|
AsyncListUtil.this.mBackgroundProxy.recycleTile(addOrReplace);
|
|
}
|
|
int i2 = tile.mStartPosition + tile.mItemCount;
|
|
int i3 = 0;
|
|
while (i3 < AsyncListUtil.this.mMissingPositions.size()) {
|
|
int keyAt = AsyncListUtil.this.mMissingPositions.keyAt(i3);
|
|
if (tile.mStartPosition > keyAt || keyAt >= i2) {
|
|
i3++;
|
|
} else {
|
|
AsyncListUtil.this.mMissingPositions.removeAt(i3);
|
|
AsyncListUtil.this.mViewCallback.onItemLoaded(keyAt);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override // androidx.recyclerview.widget.ThreadUtil.MainThreadCallback
|
|
public void removeTile(int i, int i2) {
|
|
if (isRequestedGeneration(i)) {
|
|
TileList.Tile<T> removeAtPos = AsyncListUtil.this.mTileList.removeAtPos(i2);
|
|
if (removeAtPos == null) {
|
|
Log.e("AsyncListUtil", "tile not found @" + i2);
|
|
return;
|
|
}
|
|
AsyncListUtil.this.mBackgroundProxy.recycleTile(removeAtPos);
|
|
}
|
|
}
|
|
|
|
@Override // androidx.recyclerview.widget.ThreadUtil.MainThreadCallback
|
|
public void updateItemCount(int i, int i2) {
|
|
if (isRequestedGeneration(i)) {
|
|
AsyncListUtil asyncListUtil = AsyncListUtil.this;
|
|
asyncListUtil.mItemCount = i2;
|
|
asyncListUtil.mViewCallback.onDataRefresh();
|
|
AsyncListUtil asyncListUtil2 = AsyncListUtil.this;
|
|
asyncListUtil2.mDisplayedGeneration = asyncListUtil2.mRequestedGeneration;
|
|
recycleAllTiles();
|
|
AsyncListUtil asyncListUtil3 = AsyncListUtil.this;
|
|
asyncListUtil3.mAllowScrollHints = false;
|
|
asyncListUtil3.updateRange();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* renamed from: androidx.recyclerview.widget.AsyncListUtil$2 reason: invalid class name */
|
|
public class AnonymousClass2 implements ThreadUtil.BackgroundCallback<T> {
|
|
private int mFirstRequiredTileStart;
|
|
private int mGeneration;
|
|
private int mItemCount;
|
|
private int mLastRequiredTileStart;
|
|
public final SparseBooleanArray mLoadedTiles = new SparseBooleanArray();
|
|
private TileList.Tile<T> mRecycledRoot;
|
|
|
|
public AnonymousClass2() {
|
|
}
|
|
|
|
private TileList.Tile<T> acquireTile() {
|
|
TileList.Tile<T> tile = this.mRecycledRoot;
|
|
if (tile != null) {
|
|
this.mRecycledRoot = tile.mNext;
|
|
return tile;
|
|
}
|
|
AsyncListUtil asyncListUtil = AsyncListUtil.this;
|
|
return new TileList.Tile<>(asyncListUtil.mTClass, asyncListUtil.mTileSize);
|
|
}
|
|
|
|
private void addTile(TileList.Tile<T> tile) {
|
|
this.mLoadedTiles.put(tile.mStartPosition, true);
|
|
AsyncListUtil.this.mMainThreadProxy.addTile(this.mGeneration, tile);
|
|
}
|
|
|
|
private void flushTileCache(int i) {
|
|
int maxCachedTiles = AsyncListUtil.this.mDataCallback.getMaxCachedTiles();
|
|
while (this.mLoadedTiles.size() >= maxCachedTiles) {
|
|
int keyAt = this.mLoadedTiles.keyAt(0);
|
|
SparseBooleanArray sparseBooleanArray = this.mLoadedTiles;
|
|
int keyAt2 = sparseBooleanArray.keyAt(sparseBooleanArray.size() - 1);
|
|
int i2 = this.mFirstRequiredTileStart - keyAt;
|
|
int i3 = keyAt2 - this.mLastRequiredTileStart;
|
|
if (i2 > 0 && (i2 >= i3 || i == 2)) {
|
|
removeTile(keyAt);
|
|
} else if (i3 <= 0) {
|
|
return;
|
|
} else {
|
|
if (i2 < i3 || i == 1) {
|
|
removeTile(keyAt2);
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private int getTileStart(int i) {
|
|
return i - (i % AsyncListUtil.this.mTileSize);
|
|
}
|
|
|
|
private boolean isTileLoaded(int i) {
|
|
return this.mLoadedTiles.get(i);
|
|
}
|
|
|
|
private void log(String str, Object... objArr) {
|
|
StringBuilder K = a.K("[BKGR] ");
|
|
K.append(String.format(str, objArr));
|
|
Log.d("AsyncListUtil", K.toString());
|
|
}
|
|
|
|
private void removeTile(int i) {
|
|
this.mLoadedTiles.delete(i);
|
|
AsyncListUtil.this.mMainThreadProxy.removeTile(this.mGeneration, i);
|
|
}
|
|
|
|
private void requestTiles(int i, int i2, int i3, boolean z2) {
|
|
int i4 = i;
|
|
while (i4 <= i2) {
|
|
AsyncListUtil.this.mBackgroundProxy.loadTile(z2 ? (i2 + i) - i4 : i4, i3);
|
|
i4 += AsyncListUtil.this.mTileSize;
|
|
}
|
|
}
|
|
|
|
@Override // androidx.recyclerview.widget.ThreadUtil.BackgroundCallback
|
|
public void loadTile(int i, int i2) {
|
|
if (!isTileLoaded(i)) {
|
|
TileList.Tile<T> acquireTile = acquireTile();
|
|
acquireTile.mStartPosition = i;
|
|
int min = Math.min(AsyncListUtil.this.mTileSize, this.mItemCount - i);
|
|
acquireTile.mItemCount = min;
|
|
AsyncListUtil.this.mDataCallback.fillData(acquireTile.mItems, acquireTile.mStartPosition, min);
|
|
flushTileCache(i2);
|
|
addTile(acquireTile);
|
|
}
|
|
}
|
|
|
|
@Override // androidx.recyclerview.widget.ThreadUtil.BackgroundCallback
|
|
public void recycleTile(TileList.Tile<T> tile) {
|
|
AsyncListUtil.this.mDataCallback.recycleData(tile.mItems, tile.mItemCount);
|
|
tile.mNext = this.mRecycledRoot;
|
|
this.mRecycledRoot = tile;
|
|
}
|
|
|
|
@Override // androidx.recyclerview.widget.ThreadUtil.BackgroundCallback
|
|
public void refresh(int i) {
|
|
this.mGeneration = i;
|
|
this.mLoadedTiles.clear();
|
|
int refreshData = AsyncListUtil.this.mDataCallback.refreshData();
|
|
this.mItemCount = refreshData;
|
|
AsyncListUtil.this.mMainThreadProxy.updateItemCount(this.mGeneration, refreshData);
|
|
}
|
|
|
|
@Override // androidx.recyclerview.widget.ThreadUtil.BackgroundCallback
|
|
public void updateRange(int i, int i2, int i3, int i4, int i5) {
|
|
if (i <= i2) {
|
|
int tileStart = getTileStart(i);
|
|
int tileStart2 = getTileStart(i2);
|
|
this.mFirstRequiredTileStart = getTileStart(i3);
|
|
int tileStart3 = getTileStart(i4);
|
|
this.mLastRequiredTileStart = tileStart3;
|
|
if (i5 == 1) {
|
|
requestTiles(this.mFirstRequiredTileStart, tileStart2, i5, true);
|
|
requestTiles(tileStart2 + AsyncListUtil.this.mTileSize, this.mLastRequiredTileStart, i5, false);
|
|
return;
|
|
}
|
|
requestTiles(tileStart, tileStart3, i5, false);
|
|
requestTiles(this.mFirstRequiredTileStart, tileStart - AsyncListUtil.this.mTileSize, i5, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static abstract class DataCallback<T> {
|
|
@WorkerThread
|
|
public abstract void fillData(@NonNull T[] tArr, int i, int i2);
|
|
|
|
@WorkerThread
|
|
public int getMaxCachedTiles() {
|
|
return 10;
|
|
}
|
|
|
|
@WorkerThread
|
|
public void recycleData(@NonNull T[] tArr, int i) {
|
|
}
|
|
|
|
@WorkerThread
|
|
public abstract int refreshData();
|
|
}
|
|
|
|
public static abstract class ViewCallback {
|
|
public static final int HINT_SCROLL_ASC = 2;
|
|
public static final int HINT_SCROLL_DESC = 1;
|
|
public static final int HINT_SCROLL_NONE = 0;
|
|
|
|
@UiThread
|
|
public void extendRangeInto(@NonNull int[] iArr, @NonNull int[] iArr2, int i) {
|
|
int i2 = (iArr[1] - iArr[0]) + 1;
|
|
int i3 = i2 / 2;
|
|
iArr2[0] = iArr[0] - (i == 1 ? i2 : i3);
|
|
int i4 = iArr[1];
|
|
if (i != 2) {
|
|
i2 = i3;
|
|
}
|
|
iArr2[1] = i4 + i2;
|
|
}
|
|
|
|
@UiThread
|
|
public abstract void getItemRangeInto(@NonNull int[] iArr);
|
|
|
|
@UiThread
|
|
public abstract void onDataRefresh();
|
|
|
|
@UiThread
|
|
public abstract void onItemLoaded(int i);
|
|
}
|
|
|
|
public AsyncListUtil(@NonNull Class<T> cls, int i, @NonNull DataCallback<T> dataCallback, @NonNull ViewCallback viewCallback) {
|
|
AnonymousClass1 r0 = new AnonymousClass1();
|
|
this.mMainThreadCallback = r0;
|
|
AnonymousClass2 r1 = new AnonymousClass2();
|
|
this.mBackgroundCallback = r1;
|
|
this.mTClass = cls;
|
|
this.mTileSize = i;
|
|
this.mDataCallback = dataCallback;
|
|
this.mViewCallback = viewCallback;
|
|
this.mTileList = new TileList<>(i);
|
|
MessageThreadUtil messageThreadUtil = new MessageThreadUtil();
|
|
this.mMainThreadProxy = messageThreadUtil.getMainThreadProxy(r0);
|
|
this.mBackgroundProxy = messageThreadUtil.getBackgroundProxy(r1);
|
|
refresh();
|
|
}
|
|
|
|
private boolean isRefreshPending() {
|
|
return this.mRequestedGeneration != this.mDisplayedGeneration;
|
|
}
|
|
|
|
@Nullable
|
|
public T getItem(int i) {
|
|
if (i < 0 || i >= this.mItemCount) {
|
|
throw new IndexOutOfBoundsException(i + " is not within 0 and " + this.mItemCount);
|
|
}
|
|
T itemAt = this.mTileList.getItemAt(i);
|
|
if (itemAt == null && !isRefreshPending()) {
|
|
this.mMissingPositions.put(i, 0);
|
|
}
|
|
return itemAt;
|
|
}
|
|
|
|
public int getItemCount() {
|
|
return this.mItemCount;
|
|
}
|
|
|
|
public void log(String str, Object... objArr) {
|
|
StringBuilder K = a.K("[MAIN] ");
|
|
K.append(String.format(str, objArr));
|
|
Log.d("AsyncListUtil", K.toString());
|
|
}
|
|
|
|
public void onRangeChanged() {
|
|
if (!isRefreshPending()) {
|
|
updateRange();
|
|
this.mAllowScrollHints = true;
|
|
}
|
|
}
|
|
|
|
public void refresh() {
|
|
this.mMissingPositions.clear();
|
|
ThreadUtil.BackgroundCallback<T> backgroundCallback = this.mBackgroundProxy;
|
|
int i = this.mRequestedGeneration + 1;
|
|
this.mRequestedGeneration = i;
|
|
backgroundCallback.refresh(i);
|
|
}
|
|
|
|
public void updateRange() {
|
|
this.mViewCallback.getItemRangeInto(this.mTmpRange);
|
|
int[] iArr = this.mTmpRange;
|
|
if (iArr[0] <= iArr[1] && iArr[0] >= 0 && iArr[1] < this.mItemCount) {
|
|
if (!this.mAllowScrollHints) {
|
|
this.mScrollHint = 0;
|
|
} else {
|
|
int i = iArr[0];
|
|
int[] iArr2 = this.mPrevRange;
|
|
if (i > iArr2[1] || iArr2[0] > iArr[1]) {
|
|
this.mScrollHint = 0;
|
|
} else if (iArr[0] < iArr2[0]) {
|
|
this.mScrollHint = 1;
|
|
} else if (iArr[0] > iArr2[0]) {
|
|
this.mScrollHint = 2;
|
|
}
|
|
}
|
|
int[] iArr3 = this.mPrevRange;
|
|
iArr3[0] = iArr[0];
|
|
iArr3[1] = iArr[1];
|
|
this.mViewCallback.extendRangeInto(iArr, this.mTmpRangeExtended, this.mScrollHint);
|
|
int[] iArr4 = this.mTmpRangeExtended;
|
|
iArr4[0] = Math.min(this.mTmpRange[0], Math.max(iArr4[0], 0));
|
|
int[] iArr5 = this.mTmpRangeExtended;
|
|
iArr5[1] = Math.max(this.mTmpRange[1], Math.min(iArr5[1], this.mItemCount - 1));
|
|
ThreadUtil.BackgroundCallback<T> backgroundCallback = this.mBackgroundProxy;
|
|
int[] iArr6 = this.mTmpRange;
|
|
int i2 = iArr6[0];
|
|
int i3 = iArr6[1];
|
|
int[] iArr7 = this.mTmpRangeExtended;
|
|
backgroundCallback.updateRange(i2, i3, iArr7[0], iArr7[1], this.mScrollHint);
|
|
}
|
|
}
|
|
}
|