Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b4b99bf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Evict thumbnail caches and delay dismissing spinner on refresh finish."...

Merge "Evict thumbnail caches and delay dismissing spinner on refresh finish." into nyc-andromeda-dev
parents 09e0337c eba5bb90
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
@@ -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,13 +137,32 @@ 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);
        synchronized (sizeMap) {
            sizeMap.remove(size);
+21 −1
Original line number Diff line number Diff line
@@ -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
+12 −0
Original line number Diff line number Diff line
@@ -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());