Android Open Source - android-http Lru Cache






From Project

Back to project page android-http.

License

The source code is released under:

Apache License

If you think the Android project android-http listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2011 The Android Open Source Project
 *// w w w  .ja  va2  s  . c om
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package at.diamonddogs.android.support.v4.util;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Static library version of {@link android.util.LruCache}. Used to write apps
 * that run on API levels prior to 12. When running on API level 12 or above,
 * this implementation is still used; it does not try to switch to the
 * framework's implementation. See the framework SDK documentation for a class
 * overview.
 */
public class LruCache<K, V> {
  private final LinkedHashMap<K, V> map;

  /** Size of this cache in units. Not necessarily the number of elements. */
  private int size;
  private int maxSize;

  private int putCount;
  private int createCount;
  private int evictionCount;
  private int hitCount;
  private int missCount;

  /**
   * @param maxSize
   *            for caches that do not override {@link #sizeOf}, this is the
   *            maximum number of entries in the cache. For all other caches,
   *            this is the maximum sum of the sizes of the entries in this
   *            cache.
   */
  public LruCache(int maxSize) {
    if (maxSize <= 0) {
      throw new IllegalArgumentException("maxSize <= 0");
    }
    this.maxSize = maxSize;
    this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
  }

  public LinkedHashMap<K, V> getMap() {
    return map;
  }

  /**
   * Returns the value for {@code key} if it exists in the cache or can be
   * created by {@code #create}. If a value was returned, it is moved to the
   * head of the queue. This returns null if a value is not cached and cannot
   * be created.
   */
  public final V get(K key) {
    if (key == null) {
      throw new NullPointerException("key == null");
    }

    V mapValue;
    synchronized (this) {
      mapValue = map.get(key);
      if (mapValue != null) {
        hitCount++;
        return mapValue;
      }
      missCount++;
    }

    /*
     * Attempt to create a value. This may take a long time, and the map may
     * be different when create() returns. If a conflicting value was added
     * to the map while create() was working, we leave that value in the map
     * and release the created value.
     */

    V createdValue = create(key);
    if (createdValue == null) {
      return null;
    }

    synchronized (this) {
      createCount++;
      mapValue = map.put(key, createdValue);

      if (mapValue != null) {
        // There was a conflict so undo that last put
        map.put(key, mapValue);
      } else {
        size += safeSizeOf(key, createdValue);
      }
    }

    if (mapValue != null) {
      entryRemoved(false, key, createdValue, mapValue);
      return mapValue;
    } else {
      trimToSize(maxSize);
      return createdValue;
    }
  }

  /**
   * Caches {@code value} for {@code key}. The value is moved to the head of
   * the queue.
   * 
   * @return the previous value mapped by {@code key}.
   */
  public final V put(K key, V value) {
    if (key == null || value == null) {
      throw new NullPointerException("key == null || value == null");
    }

    V previous;
    synchronized (this) {
      putCount++;
      size += safeSizeOf(key, value);
      previous = map.put(key, value);
      if (previous != null) {
        size -= safeSizeOf(key, previous);
      }
    }

    if (previous != null) {
      entryRemoved(false, key, previous, value);
    }

    trimToSize(maxSize);
    return previous;
  }

  /**
   * @param maxSize
   *            the maximum size of the cache before returning. May be -1 to
   *            evict even 0-sized elements.
   */
  private void trimToSize(int maxSize) {
    while (true) {
      K key;
      V value;
      synchronized (this) {
        if (size < 0 || (map.isEmpty() && size != 0)) {
          throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");
        }

        if (size <= maxSize || map.isEmpty()) {
          break;
        }

        Map.Entry<K, V> toEvict = map.entrySet().iterator().next();
        key = toEvict.getKey();
        value = toEvict.getValue();
        map.remove(key);
        size -= safeSizeOf(key, value);
        evictionCount++;
      }

      entryRemoved(true, key, value, null);
    }
  }

  /**
   * Removes the entry for {@code key} if it exists.
   * 
   * @return the previous value mapped by {@code key}.
   */
  public final V remove(K key) {
    if (key == null) {
      throw new NullPointerException("key == null");
    }

    V previous;
    synchronized (this) {
      previous = map.remove(key);
      if (previous != null) {
        size -= safeSizeOf(key, previous);
      }
    }

    if (previous != null) {
      entryRemoved(false, key, previous, null);
    }

    return previous;
  }

  /**
   * Called for entries that have been evicted or removed. This method is
   * invoked when a value is evicted to make space, removed by a call to
   * {@link #remove}, or replaced by a call to {@link #put}. The default
   * implementation does nothing.
   * 
   * <p>
   * The method is called without synchronization: other threads may access
   * the cache while this method is executing.
   * 
   * @param evicted
   *            true if the entry is being removed to make space, false if the
   *            removal was caused by a {@link #put} or {@link #remove}.
   * @param newValue
   *            the new value for {@code key}, if it exists. If non-null, this
   *            removal was caused by a {@link #put}. Otherwise it was caused
   *            by an eviction or a {@link #remove}.
   */
  protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {
  }

  /**
   * Called after a cache miss to compute a value for the corresponding key.
   * Returns the computed value or null if no value can be computed. The
   * default implementation returns null.
   * 
   * <p>
   * The method is called without synchronization: other threads may access
   * the cache while this method is executing.
   * 
   * <p>
   * If a value for {@code key} exists in the cache when this method returns,
   * the created value will be released with {@link #entryRemoved} and
   * discarded. This can occur when multiple threads request the same key at
   * the same time (causing multiple values to be created), or when one thread
   * calls {@link #put} while another is creating a value for the same key.
   */
  protected V create(K key) {
    return null;
  }

  private int safeSizeOf(K key, V value) {
    int result = sizeOf(key, value);
    if (result < 0) {
      throw new IllegalStateException("Negative size: " + key + "=" + value);
    }
    return result;
  }

  /**
   * Returns the size of the entry for {@code key} and {@code value} in
   * user-defined units. The default implementation returns 1 so that size is
   * the number of entries and max size is the maximum number of entries.
   * 
   * <p>
   * An entry's size must not change while it is in the cache.
   */
  protected int sizeOf(K key, V value) {
    return 1;
  }

  /**
   * Clear the cache, calling {@link #entryRemoved} on each removed entry.
   */
  public final void evictAll() {
    trimToSize(-1); // -1 will evict 0-sized elements
  }

  /**
   * For caches that do not override {@link #sizeOf}, this returns the number
   * of entries in the cache. For all other caches, this returns the sum of
   * the sizes of the entries in this cache.
   */
  public synchronized final int size() {
    return size;
  }

  /**
   * For caches that do not override {@link #sizeOf}, this returns the maximum
   * number of entries in the cache. For all other caches, this returns the
   * maximum sum of the sizes of the entries in this cache.
   */
  public synchronized final int maxSize() {
    return maxSize;
  }

  /**
   * Returns the number of times {@link #get} returned a value.
   */
  public synchronized final int hitCount() {
    return hitCount;
  }

  /**
   * Returns the number of times {@link #get} returned null or required a new
   * value to be created.
   */
  public synchronized final int missCount() {
    return missCount;
  }

  /**
   * Returns the number of times {@link #create(Object)} returned a value.
   */
  public synchronized final int createCount() {
    return createCount;
  }

  /**
   * Returns the number of times {@link #put} was called.
   */
  public synchronized final int putCount() {
    return putCount;
  }

  /**
   * Returns the number of values that have been evicted.
   */
  public synchronized final int evictionCount() {
    return evictionCount;
  }

  /**
   * Returns a copy of the current contents of the cache, ordered from least
   * recently accessed to most recently accessed.
   */
  public synchronized final Map<K, V> snapshot() {
    return new LinkedHashMap<K, V>(map);
  }

  @Override
  public synchronized final String toString() {
    int accesses = hitCount + missCount;
    int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
    return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", maxSize, hitCount, missCount, hitPercent);
  }
}




Java Source Code List

at.diamonddogs.android.support.v4.util.LruCache.java
at.diamonddogs.builder.WebRequestBuilderConfiguration.java
at.diamonddogs.builder.WebRequestBuilderDefaultConfig.java
at.diamonddogs.builder.WebRequestBuilder.java
at.diamonddogs.contentprovider.AbstractDefaultContentProvider.java
at.diamonddogs.contentprovider.CacheContentProvider.java
at.diamonddogs.data.adapter.ReplyAdapter.java
at.diamonddogs.data.adapter.database.DataBaseAdapterCacheInformation.java
at.diamonddogs.data.adapter.database.DatabaseAdapter.java
at.diamonddogs.data.adapter.database.Query.java
at.diamonddogs.data.adapter.parcelable.ParcelableAdapterTempFile.java
at.diamonddogs.data.adapter.parcelable.ParcelableAdapterWebReply.java
at.diamonddogs.data.adapter.parcelable.ParcelableAdapterWebRequest.java
at.diamonddogs.data.adapter.parcelable.ParcelableAdapter.java
at.diamonddogs.data.adapter.soap.SoapByteArrayAdapter.java
at.diamonddogs.data.adapter.soap.SoapReplyAdapter.java
at.diamonddogs.data.adapter.soap.SoapRequestAdapter.java
at.diamonddogs.data.dataobjects.CacheInformation.java
at.diamonddogs.data.dataobjects.NonTimeCriticalTaskQueueDefaultConfiguration.java
at.diamonddogs.data.dataobjects.NonTimeCriticalTask.java
at.diamonddogs.data.dataobjects.NonTimeCriticalWebRequest.java
at.diamonddogs.data.dataobjects.Reply.java
at.diamonddogs.data.dataobjects.Request.java
at.diamonddogs.data.dataobjects.SoapReply.java
at.diamonddogs.data.dataobjects.SoapRequest.java
at.diamonddogs.data.dataobjects.TempFile.java
at.diamonddogs.data.dataobjects.WebReply.java
at.diamonddogs.data.dataobjects.WebRequest.java
at.diamonddogs.data.parser.JSONArrayProxy.java
at.diamonddogs.data.parser.JSONObjectProxy.java
at.diamonddogs.data.parser.ParserProxy.java
at.diamonddogs.example.http.activity.CachingExampleActivity.java
at.diamonddogs.example.http.activity.HttpExampleActivity.java
at.diamonddogs.example.http.activity.HttpOrderedAsyncAssisiterExampleActivity.java
at.diamonddogs.example.http.activity.HttpServiceAssisterExampleActivity.java
at.diamonddogs.example.http.activity.ImageLoadingExampleListActivity.java
at.diamonddogs.example.http.activity.NonTimeCriticalExampleActivity.java
at.diamonddogs.example.http.activity.StartActivity.java
at.diamonddogs.example.http.dataobject.Example.java
at.diamonddogs.example.http.dataobject.NonTimeCriticalExampleConfiguration.java
at.diamonddogs.example.http.dataobject.Tripple.java
at.diamonddogs.example.http.dataobject.Weather.java
at.diamonddogs.example.http.dataobject.WebComic.java
at.diamonddogs.example.http.factory.NonTimeCriticalExampleConfigFactory.java
at.diamonddogs.example.http.processor.RssProcessor.java
at.diamonddogs.example.http.processor.WeatherProcessor.java
at.diamonddogs.example.http.processor.WebComicProcessor.java
at.diamonddogs.example.http.view.adapter.ImageLoadingExampleAdapter.java
at.diamonddogs.exception.CacheManagerException.java
at.diamonddogs.exception.DatabaseAdapterException.java
at.diamonddogs.exception.ProcessorExeception.java
at.diamonddogs.exception.ServiceException.java
at.diamonddogs.exception.WebClientException.java
at.diamonddogs.net.WebClientDefaultHttpClient.java
at.diamonddogs.net.WebClientFactory.java
at.diamonddogs.net.WebClientHttpURLConnection.java
at.diamonddogs.net.WebClient.java
at.diamonddogs.net.ssl.CustomSSLSocketFactory.java
at.diamonddogs.net.ssl.CustomX509TrustManager.java
at.diamonddogs.net.ssl.SSLHelper.java
at.diamonddogs.nontimecritical.NonTimeCriticalTaskManager.java
at.diamonddogs.nontimecritical.NonTimeCriticalTaskQueueConfigurationDefaultFactory.java
at.diamonddogs.nontimecritical.NonTimeCriticalTaskQueue.java
at.diamonddogs.service.CacheService.java
at.diamonddogs.service.importservice.GenericImportService.java
at.diamonddogs.service.importservice.ImportServiceContract.java
at.diamonddogs.service.importservice.ImportService.java
at.diamonddogs.service.importservice.OrderedImportServiceContract.java
at.diamonddogs.service.importservice.OrderedImportService.java
at.diamonddogs.service.net.HttpOrderedAsyncAssister.java
at.diamonddogs.service.net.HttpServiceAssister.java
at.diamonddogs.service.net.HttpService.java
at.diamonddogs.service.net.ServiceProcessorIdGenerator.java
at.diamonddogs.service.processor.AdjustableImageProcessor.java
at.diamonddogs.service.processor.DataProcessor.java
at.diamonddogs.service.processor.DummyProcessor.java
at.diamonddogs.service.processor.HeadRequestProcessor.java
at.diamonddogs.service.processor.ImageProcessor.java
at.diamonddogs.service.processor.JSONArrayProcessor.java
at.diamonddogs.service.processor.JSONProcessor.java
at.diamonddogs.service.processor.RawDataProcessor.java
at.diamonddogs.service.processor.ServiceProcessorMessageUtil.java
at.diamonddogs.service.processor.ServiceProcessor.java
at.diamonddogs.service.processor.SoapProcessor.java
at.diamonddogs.service.processor.StreamProcessor.java
at.diamonddogs.service.processor.SynchronousProcessor.java
at.diamonddogs.service.processor.SynchronousXmlProcessorNoDom.java
at.diamonddogs.service.processor.XMLProcessorNoDom.java
at.diamonddogs.service.processor.XMLProcessor.java
at.diamonddogs.service.processor.XMLXPathProcessor.java
at.diamonddogs.util.AndroidUtils.java
at.diamonddogs.util.CacheManager.java
at.diamonddogs.util.ConnectivityHelper.java
at.diamonddogs.util.SoapUtil.java
at.diamonddogs.util.Utils.java
at.diamonddogs.util.WorkerQueue.java
org.apache.commons.codec.CharEncoding.java
org.apache.commons.codec.binary.Hex.java
org.apache.commons.codec.binary.StringUtils.java