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

    maybeUpdateCacheParams();

    final Entry<K, V> oldLFUExclusive;
    final Entry<K, V> oldMFUExclusive;
    CloseableReference<V> oldRefToClose = null;
    CloseableReference<V> clientRef = null;
    synchronized (this) {
      // remove the old item (if any) as it is stale now
      oldLFUExclusive = mLeastFrequentlyUsedExclusiveEntries.remove(key);
      oldMFUExclusive = mMostFrequentlyUsedExclusiveEntries.remove(key);
      final boolean notPresentInBoth = oldLFUExclusive == null || oldMFUExclusive == null;
      Preconditions.checkState(notPresentInBoth);
      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);
        // check if the key was recently evicted and restore its state
        Integer storedAccessCount = mLeastFrequentlyUsedKeysGhostList.getValue(key);
        newEntry.accessCount = storedAccessCount != null ? storedAccessCount : 0;
        mCachedEntries.put(key, newEntry);
        clientRef = newClientReference(newEntry);
      }
    }
    CloseableReference.closeSafely(oldRefToClose);
    maybeNotifyExclusiveEntryRemoval(oldLFUExclusive, oldMFUExclusive);

    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/AbstractAdaptiveCountingMemoryCache.java