附SoftHashmap 的源碼一份,相信看過之後,大家會對 Reference 機制的應用有更深入的理解。
- package com. *** .widget;
- // : SoftHashMap.Java
- import Java.util. * ;
- import Java.lang.ref. * ;
- import android.util.Log;
- public class SoftHashMap extends AbstractMap {
- /** The internal HashMap that will hold the SoftReference. */
- private final Map hash = new HashMap();
- /** The number of "hard" references to hold internally. */
- private final int HARD_SIZE;
- /** The FIFO list of hard references, order of last Access. */
- private final LinkedList hardCache = new LinkedList();
- /** Reference queue for cleared SoftReference objects. */
- private ReferenceQueue queue = new ReferenceQueue();
- // Strong Reference number
- public SoftHashMap() { this ( 100 ); }
- public SoftHashMap( int hardSize) { HARD_SIZE = hardSize; }
- public Object get(Object key) {
- Object result = null ;
- // We get the SoftReference represented by that key
- SoftReference soft_ref = (SoftReference)hash.get(key);
- if (soft_ref != null ) {
- // From the SoftReference we get the value, which can be
- // null if it was not in the map, or it was removed in
- // the processQueue() method defined below
- result = soft_ref.get();
- if (result == null ) {
- // If the value has been garbage collected, remove the
- // entry from the HashMap.
- hash.remove(key);
- } else {
- // We now add this object to the beginning of the hard
- // reference queue. One reference can occur more than
- // once, because lookups of the FIFO queue are slow, so
- // we don't want to search through it each time to remove
- // duplicates.
- // keep recent use object in memory
- hardCache.addFirst(result);
- if (hardCache.size() > HARD_SIZE) {
- // Remove the last entry if list longer than HARD_SIZE
- hardCache.removeLast();
- }
- }
- }
- return result;
- }
- /** We define our own subclass of SoftReference which contains
- not only the value but also the key to make it easIEr to find
- the entry in the HashMap after it's been garbage collected. */
- private static class SoftValue extends SoftReference {
- private final Object key; // always make data member final
- /** Did you know that an outer class can Access private data
- members and methods of an inner class? I didn't know that!
- I thought it was only the inner class who could Access the
- outer class's private information. An outer class can also
- Access private members of an inner class inside its inner
- class. */
- private SoftValue(Object k, Object key, ReferenceQueue q) {
- super (k, q);
- this .key = key;
- }
- }
- /** Here we go through the ReferenceQueue and remove garbage
- collected SoftValue objects from the HashMap by looking them
- up using the SoftValue.key data member. */
- public void processQueue() {
- SoftValue sv;
- while ((sv = (SoftValue)queue.poll()) != null ) {
- if (sv.get() == null ) {
- Log.e( " processQueue " , " null " );
- } else {
- Log.e( " processQueue " , " Not null " );
- }
- hash.remove(sv.key); // we can Access private data!
- Log.e( " SoftHashMap " , " release " + sv.key);
- }
- }
- /** Here we put the key, value pair into the HashMap using
- a SoftValue object. */
- public Object put(Object key, Object value) {
- processQueue(); // throw out garbage collected values first
- Log.e( " SoftHashMap " , " put into " + key);
- return hash.put(key, new SoftValue(value, key, queue));
- }
- public Object remove(Object key) {
- processQueue(); // throw out garbage collected values first
- return hash.remove(key);
- }
- public void clear() {
- hardCache.clear();
- processQueue(); // throw out garbage collected values
- hash.clear();
- }
- public int size() {
- processQueue(); // throw out garbage collected values first
- return hash.size();
- }
- public Set entrySet() {
- // no, no, you may NOT do that!!! GRRR
- throw new UnsupportedOperationException();
- }
- }