Evict thumbnail caches and delay dismissing spinner on refresh finish.

Bug: 28334455
Change-Id: I338f83744d7f8b2fe9a9265dcab7ed4ec81edbfb
(cherry picked from commit dce173d1a011c07205b4b90da79d24d08e4cf90a)
This commit is contained in:
Garfield, Tan
2016-07-22 10:30:49 -07:00
committed by Garfield Tan
parent d172ebb612
commit 996aa3ba1a
3 changed files with 61 additions and 3 deletions

View File

@@ -111,6 +111,13 @@ public class ThumbnailCache {
return Result.obtainMiss();
}
/**
* Puts a thumbnail for the given uri and size in to the cache.
* @param uri the uri of the thumbnail
* @param size the size of the thumbnail
* @param thumbnail the thumbnail to put in cache
* @param lastModified last modified value of the thumbnail to track its validity
*/
public void putThumbnail(Uri uri, Point size, Bitmap thumbnail, long lastModified) {
Pair<Uri, Point> cacheKey = Pair.create(uri, size);
@@ -130,14 +137,33 @@ public class ThumbnailCache {
}
}
/**
* Removes all thumbnail cache associated to the given uri.
* @param uri the uri which thumbnail cache to remove
*/
public void removeUri(Uri uri) {
TreeMap<Point, Pair<Uri, Point>> sizeMap;
synchronized (mSizeIndex) {
sizeMap = mSizeIndex.get(uri);
}
if (sizeMap != null) {
// Create an array to hold all values to avoid ConcurrentModificationException because
// removeKey() will be called by LruCache but we can't modify the map while we're
// iterating over the collection of values.
for (Pair<Uri, Point> index : sizeMap.values().toArray(new Pair[0])) {
mCache.remove(index);
}
}
}
private void removeKey(Uri uri, Point size) {
TreeMap<Point, Pair<Uri, Point>> sizeMap;
synchronized (mSizeIndex) {
sizeMap = mSizeIndex.get(uri);
}
// LruCache tells us to remove a key, which should exist, so sizeMap can't be null.
assert (sizeMap != null);
assert(sizeMap != null);
synchronized (sizeMap) {
sizeMap.remove(size);
}

View File

@@ -42,6 +42,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
@@ -92,6 +93,7 @@ import com.android.documentsui.Shared;
import com.android.documentsui.Snackbars;
import com.android.documentsui.State;
import com.android.documentsui.State.ViewMode;
import com.android.documentsui.ThumbnailCache;
import com.android.documentsui.clipping.DocumentClipper;
import com.android.documentsui.clipping.UrisSupplier;
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
@@ -140,6 +142,9 @@ public class DirectoryFragment extends Fragment
private static final String TAG = "DirectoryFragment";
private static final int LOADER_ID = 42;
private static final int CACHE_EVICT_LIMIT = 100;
private static final int REFRESH_SPINNER_DISMISS_DELAY = 500;
private Model mModel;
private MultiSelectManager mSelectionMgr;
private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
@@ -1610,6 +1615,17 @@ public class DirectoryFragment extends Fragment
@Override
public void onRefresh() {
// Remove thumbnail cache. We do this not because we're worried about stale thumbnails as it
// should be covered by last modified value we store in thumbnail cache, but rather to give
// the user a greater sense that contents are being reloaded.
ThumbnailCache cache = DocumentsApplication.getThumbnailCache(getContext());
String[] ids = mModel.getModelIds();
int numOfEvicts = Math.min(ids.length, CACHE_EVICT_LIMIT);
for (int i = 0; i < numOfEvicts; ++i) {
cache.removeUri(mModel.getItemUri(ids[i]));
}
// Trigger loading
getLoaderManager().restartLoader(LOADER_ID, null, this);
}
@@ -1679,7 +1695,11 @@ public class DirectoryFragment extends Fragment
mTuner.onModelLoaded(mModel, mType, mSearchMode);
mRefreshLayout.setRefreshing(false);
if (mRefreshLayout.isRefreshing()) {
new Handler().postDelayed(
() -> mRefreshLayout.setRefreshing(false),
REFRESH_SPINNER_DISMISS_DELAY);
}
}
@Override

View File

@@ -176,6 +176,18 @@ public class ThumbnailCacheTest {
assertSame(SMALL_BITMAP, result.getThumbnail());
}
@Test
public void testRemoveUri() {
mCache.putThumbnail(URI_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
mCache.putThumbnail(URI_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED);
mCache.putThumbnail(URI_1, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED);
mCache.removeUri(URI_0);
assertMiss(mCache.getThumbnail(URI_0, MID_SIZE));
assertHitExact(mCache.getThumbnail(URI_1, MID_SIZE));
}
private static void assertMiss(Result result) {
assertEquals(Result.CACHE_MISS, result.getStatus());
assertFalse(result.isExactHit());