標籤:
今天發現一個問題,ApiLevel-22的Android源碼,兩個版本的LruCache:android.support.v4.util.LruCache和android.util.LruCache在移除舊的緩衝對象時的行為完全不一樣。
android.support.v4.util.LruCache在移除緩衝的時候是移除最近最少訪問的,符合LruCache的設計初衷。
android.util.LruCache在緩衝滿了的情況下,會把當前加入的直接移除掉,不符合LruCache的設計初衷。
關鍵代碼如下:
android.support.v4.util.LruCache,第15行代碼
1 private void trimToSize(int maxSize) { 2 while (true) { 3 K key; 4 V value; 5 synchronized (this) { 6 if (size < 0 || (map.isEmpty() && size != 0)) { 7 throw new IllegalStateException(getClass().getName() 8 + ".sizeOf() is reporting inconsistent results!"); 9 }10 11 if (size <= maxSize) {12 break;13 }14 15 Map.Entry<K, V> toEvict = map.eldest();16 if (toEvict == null) {17 break;18 }19 20 key = toEvict.getKey();21 value = toEvict.getValue();22 map.remove(key);23 size -= safeSizeOf(key, value);24 evictionCount++;25 }26 27 entryRemoved(true, key, value, null);28 }29 }View Code
android.util.LruCache,第20行代碼
1 private void trimToSize(int maxSize) { 2 while (true) { 3 K key; 4 V value; 5 synchronized (this) { 6 if (size < 0 || (map.isEmpty() && size != 0)) { 7 throw new IllegalStateException(getClass().getName() 8 + ".sizeOf() is reporting inconsistent results!"); 9 }10 11 if (size <= maxSize) {12 break;13 }14 15 // BEGIN LAYOUTLIB CHANGE16 // get the last item in the linked list.17 // This is not efficient, the goal here is to minimize the changes18 // compared to the platform version.19 Map.Entry<K, V> toEvict = null;20 for (Map.Entry<K, V> entry : map.entrySet()) {21 toEvict = entry;22 }23 // END LAYOUTLIB CHANGE24 25 if (toEvict == null) {26 break;27 }28 29 key = toEvict.getKey();30 value = toEvict.getValue();31 map.remove(key);32 size -= safeSizeOf(key, value);33 evictionCount++;34 }35 36 entryRemoved(true, key, value, null);37 }38 }View Code
所以最好使用Support包中的LruCache。
Android api level-22中android.support.v4.util.LruCache和android.util.LruCache的行為不一樣問題