Skip to content

Commit affc542

Browse files
Veeren Mandaliafacebook-github-bot
authored andcommitted
Adds support for dynamic caches to image pipeline
Reviewed By: oprisnik Differential Revision: D58132712 fbshipit-source-id: 3fe68754b7ac2ec50ba868fd7ba21d6a48933586
1 parent f007e8e commit affc542

6 files changed

Lines changed: 67 additions & 19 deletions

File tree

‎imagepipeline/src/main/java/com/facebook/imagepipeline/core/ImagePipeline.kt‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class ImagePipeline(
5555
encodedMemoryCache: MemoryCache<CacheKey, PooledByteBuffer>,
5656
mainBufferedDiskCache: BufferedDiskCache,
5757
smallImageBufferedDiskCache: BufferedDiskCache,
58+
dynamicBufferedDiskCaches: Map<String, BufferedDiskCache>?,
5859
cacheKeyFactory: CacheKeyFactory,
5960
threadHandoffProducerQueue: ThreadHandoffProducerQueue,
6061
suppressBitmapPrefetchingSupplier: Supplier<Boolean>,
@@ -71,6 +72,7 @@ class ImagePipeline(
7172
private val encodedMemoryCache: MemoryCache<CacheKey, PooledByteBuffer>
7273
private val mainBufferedDiskCache: BufferedDiskCache
7374
private val smallImageBufferedDiskCache: BufferedDiskCache
75+
private var dynamicBufferedDiskCaches: Map<String, BufferedDiskCache>?
7476

7577
/** @return The CacheKeyFactory implementation used by ImagePipeline */
7678
val cacheKeyFactory: CacheKeyFactory
@@ -606,6 +608,7 @@ class ImagePipeline(
606608
val cacheKey = cacheKeyFactory.getEncodedCacheKey(imageRequest, null)
607609
mainBufferedDiskCache.remove(cacheKey)
608610
smallImageBufferedDiskCache.remove(cacheKey)
611+
dynamicBufferedDiskCaches?.forEach { it.value.remove(cacheKey) }
609612
}
610613

611614
/**
@@ -632,6 +635,7 @@ class ImagePipeline(
632635
fun clearDiskCaches() {
633636
mainBufferedDiskCache.clearAll()
634637
smallImageBufferedDiskCache.clearAll()
638+
dynamicBufferedDiskCaches?.forEach { it.value.clearAll() }
635639
}
636640

637641
val usedDiskCacheSize: Long
@@ -640,7 +644,10 @@ class ImagePipeline(
640644
*
641645
* @return size in Bytes
642646
*/
643-
get() = mainBufferedDiskCache.size + smallImageBufferedDiskCache.size
647+
get() =
648+
mainBufferedDiskCache.size +
649+
smallImageBufferedDiskCache.size +
650+
(dynamicBufferedDiskCaches?.values?.sumOf { it.size } ?: 0)
644651

645652
/** Clear all the caches (memory and disk) */
646653
fun clearCaches() {
@@ -1025,6 +1032,7 @@ class ImagePipeline(
10251032
this.encodedMemoryCache = encodedMemoryCache
10261033
this.mainBufferedDiskCache = mainBufferedDiskCache
10271034
this.smallImageBufferedDiskCache = smallImageBufferedDiskCache
1035+
this.dynamicBufferedDiskCaches = dynamicBufferedDiskCaches
10281036
this.cacheKeyFactory = cacheKeyFactory
10291037
this.threadHandoffProducerQueue = threadHandoffProducerQueue
10301038
this.suppressBitmapPrefetchingSupplier = suppressBitmapPrefetchingSupplier

‎imagepipeline/src/main/java/com/facebook/imagepipeline/core/ImagePipelineFactory.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ public static synchronized void shutDown() {
143143
@Nullable private ProducerSequenceFactory mProducerSequenceFactory;
144144
@Nullable private BufferedDiskCache mSmallImageBufferedDiskCache;
145145
@Nullable private FileCache mSmallImageFileCache;
146-
147146
@Nullable private Map<String, FileCache> mDynamicFileCaches;
148147
@Nullable private ImmutableMap<String, BufferedDiskCache> mDynamicBufferedDiskCaches;
149148

@@ -350,6 +349,7 @@ private ImagePipeline createImagePipeline() {
350349
getEncodedMemoryCache(),
351350
getMainBufferedDiskCache(),
352351
getSmallImageBufferedDiskCache(),
352+
getDynamicBufferedDiskCaches(),
353353
mConfig.getCacheKeyFactory(),
354354
mThreadHandoffProducerQueue,
355355
mConfig.getExperiments().getSuppressBitmapPrefetchingSupplier(),

‎imagepipeline/src/test/java/com/facebook/imagepipeline/core/ImagePipelineTest.java‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@
4444
import com.facebook.imagepipeline.producers.ThreadHandoffProducerQueue;
4545
import com.facebook.imagepipeline.request.ImageRequest;
4646
import java.util.ArrayList;
47+
import java.util.HashMap;
4748
import java.util.List;
49+
import java.util.Map;
4850
import org.junit.Before;
4951
import org.junit.Test;
5052
import org.junit.runner.RunWith;
@@ -72,6 +74,8 @@ public class ImagePipelineTest {
7274
private MemoryCache<CacheKey, PooledByteBuffer> mEncodedMemoryCache;
7375
private BufferedDiskCache mMainDiskStorageCache;
7476
private BufferedDiskCache mSmallImageDiskStorageCache;
77+
private BufferedDiskCache mDynamicBufferedDiskCache;
78+
private Map<String, BufferedDiskCache> mDynamicBufferedDiskCaches;
7579
private RequestListener mRequestListener1;
7680
private RequestListener mRequestListener2;
7781
private ThreadHandoffProducerQueue mThreadHandoffProducerQueue;
@@ -91,6 +95,9 @@ public void setUp() throws Exception {
9195
mEncodedMemoryCache = mock(MemoryCache.class);
9296
mMainDiskStorageCache = mock(BufferedDiskCache.class);
9397
mSmallImageDiskStorageCache = mock(BufferedDiskCache.class);
98+
mDynamicBufferedDiskCache = mock(BufferedDiskCache.class);
99+
mDynamicBufferedDiskCaches = new HashMap<>();
100+
mDynamicBufferedDiskCaches.put("dynamicId1", mDynamicBufferedDiskCache);
94101
mThreadHandoffProducerQueue = mock(ThreadHandoffProducerQueue.class);
95102
mImagePipeline =
96103
new ImagePipeline(
@@ -102,6 +109,7 @@ public void setUp() throws Exception {
102109
mEncodedMemoryCache,
103110
mMainDiskStorageCache,
104111
mSmallImageDiskStorageCache,
112+
mDynamicBufferedDiskCaches,
105113
mCacheKeyFactory,
106114
mThreadHandoffProducerQueue,
107115
mSuppressBitmapPrefetchingSupplier,
@@ -468,6 +476,7 @@ public void testEvictFromDiskCache() {
468476
mImagePipeline.evictFromDiskCache(uri);
469477
verify(mMainDiskStorageCache).remove(multiKey);
470478
verify(mSmallImageDiskStorageCache).remove(multiKey);
479+
verify(mDynamicBufferedDiskCache).remove(multiKey);
471480
}
472481

473482
@Test
@@ -526,13 +535,15 @@ public void testClearDiskCaches() {
526535
mImagePipeline.clearDiskCaches();
527536
verify(mMainDiskStorageCache).clearAll();
528537
verify(mSmallImageDiskStorageCache).clearAll();
538+
verify(mDynamicBufferedDiskCache).clearAll();
529539
}
530540

531541
@Test
532542
public void testDiskCachesSize() {
533543
mImagePipeline.getUsedDiskCacheSize();
534544
verify(mMainDiskStorageCache).getSize();
535545
verify(mSmallImageDiskStorageCache).getSize();
546+
verify(mDynamicBufferedDiskCache).getSize();
536547
}
537548

538549
@Test

‎vito/core-java-impl/src/main/java/com/facebook/fresco/vito/core/impl/ImagePipelineUtilsImpl.kt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class ImagePipelineUtilsImpl(private val imageDecodeOptionsProvider: ImageDecode
8383
if (imageOptions.cacheChoice != null) {
8484
builder.cacheChoice = imageOptions.cacheChoice
8585
}
86+
if (imageOptions.diskCacheId != null) {
87+
builder.diskCacheId = imageOptions.diskCacheId
88+
}
8689
return builder
8790
}
8891

‎vito/options/src/main/java/com/facebook/fresco/vito/options/DecodedImageOptions.kt‎

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,23 @@ open class DecodedImageOptions(builder: Builder<*>) : EncodedImageOptions(builde
107107

108108
constructor() : super()
109109

110-
constructor(defaultOptions: ImageOptions) : super(defaultOptions) {
111-
resizeOptions = defaultOptions.resizeOptions
112-
rotationOptions = defaultOptions.rotationOptions
113-
postprocessor = defaultOptions.postprocessor
114-
imageDecodeOptions = defaultOptions.imageDecodeOptions
115-
roundingOptions = defaultOptions.roundingOptions
116-
borderOptions = defaultOptions.borderOptions
117-
actualImageScaleType = defaultOptions.actualImageScaleType
118-
actualFocusPoint = defaultOptions.actualImageFocusPoint
119-
localThumbnailPreviewsEnabled = defaultOptions.areLocalThumbnailPreviewsEnabled()
120-
loadThumbnailOnly = defaultOptions.loadThumbnailOnly
121-
bitmapConfig = defaultOptions.bitmapConfig
122-
progressiveDecodingEnabled = defaultOptions.isProgressiveDecodingEnabled
110+
constructor(decodedImageOptions: DecodedImageOptions) : super(decodedImageOptions) {
111+
resizeOptions = decodedImageOptions.resizeOptions
112+
rotationOptions = decodedImageOptions.rotationOptions
113+
postprocessor = decodedImageOptions.postprocessor
114+
imageDecodeOptions = decodedImageOptions.imageDecodeOptions
115+
roundingOptions = decodedImageOptions.roundingOptions
116+
borderOptions = decodedImageOptions.borderOptions
117+
actualImageScaleType = decodedImageOptions.actualImageScaleType
118+
actualFocusPoint = decodedImageOptions.actualImageFocusPoint
119+
localThumbnailPreviewsEnabled = decodedImageOptions.areLocalThumbnailPreviewsEnabled()
120+
loadThumbnailOnly = decodedImageOptions.loadThumbnailOnly
121+
bitmapConfig = decodedImageOptions.bitmapConfig
122+
progressiveDecodingEnabled = decodedImageOptions.isProgressiveDecodingEnabled
123123
}
124124

125+
constructor(defaultOptions: ImageOptions) : this(defaultOptions as DecodedImageOptions)
126+
125127
fun resize(resizeOptions: ResizeOptions?): T = modify { this.resizeOptions = resizeOptions }
126128

127129
fun rotate(rotationOptions: RotationOptions?): T = modify {

‎vito/options/src/main/java/com/facebook/fresco/vito/options/EncodedImageOptions.kt‎

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,23 @@ package com.facebook.fresco.vito.options
1010
import com.facebook.common.internal.Objects
1111
import com.facebook.imagepipeline.common.Priority
1212
import com.facebook.imagepipeline.request.ImageRequest.CacheChoice
13+
import com.facebook.imagepipeline.request.ImageRequestBuilder.BuilderException
1314

1415
open class EncodedImageOptions(builder: Builder<*>) {
1516
val priority: Priority? = builder.priority
1617
val cacheChoice: CacheChoice? = builder.cacheChoice
18+
val diskCacheId: String? = builder.diskCacheId
19+
20+
init {
21+
if (builder.cacheChoice == CacheChoice.DYNAMIC) {
22+
if (diskCacheId == null) {
23+
throw BuilderException("Disk cache id must be set for dynamic cache choice")
24+
}
25+
} else if (!diskCacheId.isNullOrEmpty()) {
26+
throw BuilderException(
27+
"Ensure that if you want to use a disk cache id, you set the CacheChoice to DYNAMIC")
28+
}
29+
}
1730

1831
override fun equals(other: Any?): Boolean {
1932
if (this === other) {
@@ -26,34 +39,45 @@ open class EncodedImageOptions(builder: Builder<*>) {
2639
}
2740

2841
protected fun equalEncodedOptions(other: EncodedImageOptions): Boolean {
29-
return Objects.equal(priority, other.priority) && Objects.equal(cacheChoice, other.cacheChoice)
42+
return Objects.equal(priority, other.priority) &&
43+
Objects.equal(cacheChoice, other.cacheChoice) &&
44+
Objects.equal(diskCacheId, other.diskCacheId)
3045
}
3146

3247
override fun hashCode(): Int {
33-
val result = priority?.hashCode() ?: 0
34-
return 31 * result + (cacheChoice?.hashCode() ?: 0)
48+
var result = priority?.hashCode() ?: 0
49+
result = 31 * result + (cacheChoice?.hashCode() ?: 0)
50+
result = 31 * result + (diskCacheId?.hashCode() ?: 0)
51+
return result
3552
}
3653

3754
override fun toString(): String = toStringHelper().toString()
3855

3956
protected open fun toStringHelper(): Objects.ToStringHelper =
40-
Objects.toStringHelper(this).add("priority", priority).add("cacheChoice", cacheChoice)
57+
Objects.toStringHelper(this)
58+
.add("priority", priority)
59+
.add("cacheChoice", cacheChoice)
60+
.add("diskCacheId", diskCacheId)
4161

4262
open class Builder<T : Builder<T>> {
4363
internal var priority: Priority? = null
4464
internal var cacheChoice: CacheChoice? = null
65+
internal var diskCacheId: String? = null
4566

4667
protected constructor()
4768

4869
protected constructor(defaultOptions: EncodedImageOptions) {
4970
priority = defaultOptions.priority
5071
cacheChoice = defaultOptions.cacheChoice
72+
diskCacheId = defaultOptions.diskCacheId
5173
}
5274

5375
fun priority(priority: Priority?): T = modify { this.priority = priority }
5476

5577
fun cacheChoice(cacheChoice: CacheChoice?): T = modify { this.cacheChoice = cacheChoice }
5678

79+
fun diskCacheId(diskCacheId: String?): T = modify { this.diskCacheId = diskCacheId }
80+
5781
open fun build(): EncodedImageOptions = EncodedImageOptions(this)
5882

5983
protected fun getThis(): T = this as T

0 commit comments

Comments
 (0)