@Override
  public @Nullable CloseableReference<V> cache(
      final K key,
      final CloseableReference<V> valueRef,
      final @Nullable EntryStateObserver<K> observer) {
    Preconditions.checkNotNull(key);
    Preconditions.checkNotNull(valueRef);

    maybeUpdateCacheParams();

    Entry<K, V> oldExclusive;
    CloseableReference<V> oldRefToClose = null;
    CloseableReference<V> clientRef = null;
    synchronized (this) {
      // remove the old item (if any) as it is stale now
      oldExclusive = mExclusiveEntries.remove(key);
      Entry<K, V> oldEntry = mCachedEntries.remove(key);
      if (oldEntry != null) {
        makeOrphan(oldEntry);
        oldRefToClose = referenceToClose(oldEntry);
      }

      V value = valueRef.get();
      int size = mValueDescriptor.getSizeInBytes(value);
      if (canCacheNewValueOfSize(size)) {
        Entry<K, V> newEntry;
        if (mStoreEntrySize) {
          newEntry = Entry.of(key, valueRef, size, observer);
        } else {
          newEntry = Entry.of(key, valueRef, observer);
        }
        mCachedEntries.put(key, newEntry);
        clientRef = newClientReference(newEntry);
      }
    }
    CloseableReference.closeSafely(oldRefToClose);
    maybeNotifyExclusiveEntryRemoval(oldExclusive);

    maybeEvictEntries();
    return clientRef;
  }
Caches the given key-value pair.

<p>Important: the client should use the returned reference instead of the original one. It is
the caller's responsibility to close the returned reference once not needed anymore.

@return the new reference to be used, null if the value cannot be cached
imagepipeline-base/src/main/java/com/facebook/imagepipeline/cache/LruCountingMemoryCache.java