Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android:LruCache緩存小結

android:LruCache緩存小結

編輯:關於Android編程

原理:

LruCache以鍵值對的形式,初始化時,需要設置緩存的大小K,超過這個大小的數據將會被清除。注意:清除的數據,是那些被先加入的數據。LruCache內部的數據結構是LinkedHashMap存儲的。這樣,LruCache就達到了緩存最近put的K個數據。


使用:
[code]

int cacheSize = 4 * 1024 * 1024; // 4MiB
   LruCache bitmapCache = new LruCache(cacheSize) {
       protected int sizeOf(String key, Bitmap value) {
           return value.getByteCount();
       
   }}

注意,緩存不同的數據,需要重寫sizeOf方法。比如,上面緩存的是圖片。本質上,這些數據都是存儲在內存中的,因此,cacheSize不易過大。


LruCache源代碼:

import java.util.LinkedHashMap;
import java.util.Map;
 
public class LruCache {
    private final LinkedHashMap map;
 
    private int size;
    private int maxSize;
 
    private int putCount;
    private int createCount;
    private int evictionCount;
    private int hitCount;
    private int missCount;
 
    public LruCache(int maxSize) {
        if (maxSize <= 0) {
            throw new IllegalArgumentException("maxSize <= 0");
        }
        this.maxSize = maxSize;
        this.map = new LinkedHashMap(0, 0.75f, true);
    }
 
    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++;
        }
 
        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;
        }
    }
 
    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;
    }
 
    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 toEvict = map.entrySet().iterator().next();
                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                size -= safeSizeOf(key, value);
                evictionCount++;
            }
 
            entryRemoved(true, key, value, null);
        }
    }
 
    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;
    }
 
    protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
 
    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;
    }
 
    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
    }
 
    public synchronized final int size() {
        return size;
    }
 
    public synchronized final int maxSize() {
        return maxSize;
    }
 
    public synchronized final int hitCount() {
        return hitCount;
    }
 
    public synchronized final int missCount() {
        return missCount;
    }
 
    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 snapshot() {
        return new LinkedHashMap(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);
    }
}


從源代碼中,我們可以清晰的看出LruCache的緩存機制。


-------------------------------------------------------------------

更多交流,Android開發聯盟QQ群:272209595


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved