文章将会被同步至微信公众号:Android部落格
从第三篇文章中可以看到Producer的初始化顺序是BitmapMemoryCacheProducer->DecodeProducer,由此看到解码成功的图片还要经过内存缓存,等于是说光内存缓存就有两份,一份编码的,一份解码的。
这边文章讲解码之后的数据缓存。
经过DecodeProducer解码之后的数据,被包裹在CloseableStaticBitmap对象中,然后向上传递。
//BitmapMemoryCacheProducer
@Override
public void produceResults(
final Consumer<CloseableReference<CloseableImage>> consumer, final ProducerContext producerContext) {
CloseableReference<CloseableImage> cachedReference = mMemoryCache.get(cacheKey);
if (cachedReference != null) {
consumer.onNewResult(cachedReference, BaseConsumer.simpleStatusForIsLast(isFinal));
cachedReference.close();
} else {
Consumer<CloseableReference<CloseableImage>> wrappedConsumer = wrapConsumer(
consumer, cacheKey, producerContext.getImageRequest().isMemoryCacheEnabled());
mInputProducer.produceResults(wrappedConsumer, producerContext);
}
}
先看看缓存里面有没有目标的数据,有的话通知其他consumer可以结束了,我这里已经取到数据了。当然目标数据要符合质量要求。
当前缓存中找不到目标数据的话,就要设置消费者来拦截并处理数据了。消费者的定义在wrapConsumer方法中:
//BitmapMemoryCacheProducer
protected Consumer<CloseableReference<CloseableImage>> wrapConsumer(){
return new DelegatingConsumer<
CloseableReference<CloseableImage>, CloseableReference<CloseableImage>>(consumer) {
@Override
public void onNewResultImpl(
CloseableReference<CloseableImage> newResult, @Status int status) {
final boolean isLast = isLast(status);
if(newResult == null && isLast){
getConsumer().onNewResult(null, status);
return;
}
CloseableReference<CloseableImage> currentCachedResult = mMemoryCache.get(cacheKey);
if (currentCachedResult != null) {
getConsumer().onNewResult(currentCachedResult, status);
return;
}
CloseableReference<CloseableImage> newCachedResult = null;
if (isMemoryCacheEnabled) {
newCachedResult = mMemoryCache.cache(cacheKey, newResult);
getConsumer().onNewResult((newCachedResult != null) ? newCachedResult : newResult, status);
}
}
}
}
三个步骤:
//CountingMemoryCache
public @Nullable CloseableReference<V> cache(
final K key, final CloseableReference<V> valueRef, final EntryStateObserver<K> observer) {
maybeUpdateCacheParams();
oldExclusive = mExclusiveEntries.remove(key);
Entry<K, V> oldEntry = mCachedEntries.remove(key);
if (oldEntry != null) {
makeOrphan(oldEntry);
oldRefToClose = referenceToClose(oldEntry);
}
if (canCacheNewValue(valueRef.get())) {
Entry<K, V> newEntry = Entry.of(key, valueRef, observer);
mCachedEntries.put(key, newEntry);
clientRef = newClientReference(newEntry);
}
maybeEvictEntries();
}
五个步骤:
再贴一下内存缓存的空间大小限制:
public class DefaultBitmapMemoryCacheParamsSupplier implements Supplier<MemoryCacheParams> {
private static final int MAX_CACHE_ENTRIES = 256;
private static final int MAX_EVICTION_QUEUE_SIZE = Integer.MAX_VALUE;
private static final int MAX_EVICTION_QUEUE_ENTRIES = Integer.MAX_VALUE;
private static final int MAX_CACHE_ENTRY_SIZE = Integer.MAX_VALUE;
private static final long PARAMS_CHECK_INTERVAL_MS = TimeUnit.MINUTES.toMillis(5);
private final ActivityManager mActivityManager;
public DefaultBitmapMemoryCacheParamsSupplier(ActivityManager activityManager) {
mActivityManager = activityManager;
}
@Override
public MemoryCacheParams get() {
return new MemoryCacheParams(
getMaxCacheSize(),
MAX_CACHE_ENTRIES,
MAX_EVICTION_QUEUE_SIZE,
MAX_EVICTION_QUEUE_ENTRIES,
MAX_CACHE_ENTRY_SIZE,
PARAMS_CHECK_INTERVAL_MS);
}
private int getMaxCacheSize() {
final int maxMemory =
Math.min(mActivityManager.getMemoryClass() * ByteConstants.MB, Integer.MAX_VALUE);
if (maxMemory < 32 * ByteConstants.MB) {
return 4 * ByteConstants.MB;
} else if (maxMemory < 64 * ByteConstants.MB) {
return 6 * ByteConstants.MB;
} else {
// We don't want to use more ashmem on Gingerbread for now, since it doesn't respond well to
// native memory pressure (doesn't throw exceptions, crashes app, crashes phone)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return 8 * ByteConstants.MB;
} else {
return maxMemory / 4;
}
}
}
}
getMemoryClass
Return the approximate per-application memory class of the current device. This gives you an idea of how hard a memory limit you should impose on your application to let the overall system work best. The returned value is in megabytes; the baseline Android memory class is 16 (which happens to be the Java heap limit of those devices); some devices with more memory may return 24 or even higher numbers.
缓存成功,返回缓存之后的数据,并将数据上传个下一个消费者。