so.contacts.hub.basefunction.imageloader.DataCache.java Source code

Java tutorial

Introduction

Here is the source code for so.contacts.hub.basefunction.imageloader.DataCache.java

Source

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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 so.contacts.hub.basefunction.imageloader;

import java.io.File;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import so.contacts.hub.ContactsApp;
import so.contacts.hub.basefunction.imageloader.utils.CacheUtils;
import so.contacts.hub.basefunction.imageloader.utils.DiskLruCache;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

/**************************************************
 * <br>
 * ??: DataCache.java <br>
 * ? : ???? ? <br>
 * : wcy <br>
 * ??: ??? <br>
 * : 2015-7-6 ?11:39:40 <br>
 * ?: 2015-7-6 1.00 ?
 **************************************************/
public class DataCache {
    private static final String TAG = "DataCache";

    /**
     * ?? 8M
     */
    private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 1024 * 8; // 8MB

    /**
     * ??
     */
    private static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB

    /**
     * ??
     */
    public static final String HTTP_CACHE_DIR = "http_";

    // Constants to easily toggle various caches
    private static final boolean DEFAULT_MEM_CACHE_ENABLED = true;

    /**
     * 
     */
    private DiskLruCache mDiskLruCache;

    /**
     * 
     */
    private LruCache<String, Object> mMemCache;

    /**
     * ???uniqueName?(?10M),?(20M)
     */
    private DataCacheParams mCacheParams;

    /**
     * ?map
     * ??????WeakReference??map????
     */
    private static Map<String, WeakReference<Bitmap>> mWeakBitmaps = Collections
            .synchronizedMap(new HashMap<String, WeakReference<Bitmap>>());;

    /**
     * Creating a new ImageCache object using the specified parameters.
     * ?parameters?new ImageCache
     * 
     * @param cacheParams The cache parameters to use to initialize the cache
     */
    public DataCache(DataCacheParams cacheParams) {
        init(cacheParams);
    }

    /**
     * Creating a new ImageCache object using the default parameters.
     * 
     * @param context The context to use
     * @param uniqueName A unique name that will be appended to the cache
     * directory
     */
    public DataCache(Context context, String uniqueName) {
        init(new DataCacheParams(context, uniqueName));
    }

    /**
     * Find and return an existing ImageCache stored in a {@link RetainCache} ,
     * if not found a new one is created using the supplied params and saved to
     * a {@link RetainCache}.
     * 
     * @param cacheParams The cache parameters to use if creating the DataCache
     * @return An existing retained DataCache object or a new one if one did not
     * exist
     */
    public static DataCache findOrCreateCache(DataCacheParams cacheParams) {
        //modify by xcx 2015-08-25 start cache?recycle?cache???cache
        // // Search for, or create an instance of the non-UI RetainObject
        //        final RetainCache mRetainObject = RetainCache.getInstance();
        //
        //        // See if we already have an ImageCache instance in RetainApplication
        //        DataCache dataCache = (DataCache) mRetainObject.getCache(cacheParams.uniqueName);
        //
        //        LogUtil.i(TAG, "datacache: " + dataCache + " uniqueName:" + cacheParams.uniqueName);
        //
        //        // No existing ImageCache, create one and store it in RetainApplication
        //        if (dataCache == null)
        //        {
        //            LogUtil.i(TAG, "datacache is created");
        //            dataCache = new DataCache(cacheParams);
        //            mRetainObject.setCache(cacheParams.uniqueName, dataCache);
        //        }

        DataCache dataCache = new DataCache(cacheParams);
        return dataCache;
        //modify by xcx 2015-08-25 end cache?recycle?cache???cache
    }

    /**
     * Get the size in bytes of a bitmap. Bitmapbyte?
     * 
     * @param bitmap
     * @return size in bytes
     */
    @TargetApi(12)
    public static int getBitmapSize(Bitmap bitmap) {
        if (CacheUtils.hasHoneycombMR1()) {
            return bitmap.getByteCount();
        }
        // Pre HC-MR1
        return bitmap.getRowBytes() * bitmap.getHeight();
    }

    /**
     * Initialize the cache, providing all parameters. ????
     * 
     * @param cacheParams The cache parameters to initialize the cache
     */
    private void init(DataCacheParams cacheParams) {
        mCacheParams = cacheParams;
        // Set up memory cache
        // 
        if (mCacheParams.memoryCacheEnabled) {
            mMemCache = new LruCache<String, Object>(mCacheParams.memCacheSize) {
                /**
                 * Measure item size in bytes rather than units which is more
                 * practical for a bitmap cache ??LruCache
                 */
                @Override
                protected int sizeOf(String key, Object obj) {
                    if (obj instanceof Bitmap) {
                        return getBitmapSize((Bitmap) obj);
                    }
                    return 0;
                }
            };
            if (mCacheParams.diskCacheDir != null) {
                mDiskLruCache = DiskLruCache.openCache(mCacheParams.diskCacheDir, mCacheParams.diskCacheSize);
            } else {
                // ?
                mCacheParams.diskCacheDir = DiskLruCache.getDiskCacheDir(ContactsApp.getInstance(),
                        HTTP_CACHE_DIR + mCacheParams.uniqueName);
                // ?
                mCacheParams.diskCacheSize = DEFAULT_DISK_CACHE_SIZE;
                mDiskLruCache = DiskLruCache.openCache(mCacheParams.diskCacheDir, mCacheParams.diskCacheSize);
            }

        }
    }

    /**
     * Adds a bitmap to both memory and disk cache.
     * 
     * @param data Unique identifier for the bitmap to store
     * @param bitmap The bitmap to store
     */
    public void addDataToCache(String data, Object result) {
        if (data == null || result == null) {
            return;
        }
        // Add to memory cache
        if (mMemCache != null) {
            mMemCache.put(data, result);
        }
        //add by xcx 2015-08-25 start ?
        if (result instanceof Bitmap) {
            mWeakBitmaps.put(data, new WeakReference<Bitmap>((Bitmap) result));
        }
        //add by xcx 2015-08-25 end ?
    }

    /**
     * Get from memory cache.
     * 
     * @param data Unique identifier for which item to get
     * @return The bitmap if found in cache, null otherwise
     */
    public Object getResultFromCache(String data) {
        if (mMemCache != null) {
            final Object mCacheResult = mMemCache.get(data);
            if (mCacheResult != null) {
                return mCacheResult;
            }
        }
        //add by xcx 2015-08-25 start ?
        if (mWeakBitmaps != null) {
            WeakReference<Bitmap> weakRef = mWeakBitmaps.get(data);
            if (weakRef != null) {
                Bitmap bitmap = weakRef.get();
                if (bitmap != null && !bitmap.isRecycled()) {
                    return bitmap;
                }
            }
        }
        //add by xcx 2015-08-25 end ?
        return null;
    }

    /**
     * Clears both the memory and disk cache associated with this ImageCache
     * object. Note that this includes disk access so this should not be
     * executed on the main/UI thread.
     */
    public void clearCache() {
        if (mMemCache != null) {
            //modify by xcx 2015-08-25 start recycle
            Map<String, Object> map = mMemCache.snapshot();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                Object value = entry.getValue();
                if (value != null && value instanceof Bitmap) {
                    Bitmap bitmap = (Bitmap) value;
                    if (bitmap != null && !bitmap.isRecycled()) {
                        bitmap.recycle();
                        bitmap = null;
                    }
                    mWeakBitmaps.remove(entry.getKey());
                }
            }
            mMemCache.evictAll();
            //modify by xcx 2015-08-25 end recycle
        }
        //add by xcx 2015-08-25 start ????
        if (mDiskLruCache != null) {
            mDiskLruCache.clearMap();
        }
        //add by xcx 2015-08-25 end ????
        System.gc();
    }

    public void removeCache(String key) {
        if (mMemCache != null) {
            mMemCache.remove(key);
        }
    }

    public DiskLruCache getDiskLruCache() {
        return mDiskLruCache;
    }

    /**
     * A holder class that contains cache parameters. ???
     * ?????
     */
    public static class DataCacheParams {

        private Context context;

        /**
         * ??
         */
        private String uniqueName;

        /**
         * ?
         */
        public int memCacheSize = DEFAULT_MEM_CACHE_SIZE;

        /**
         * ???????
         */
        public boolean memoryCacheEnabled = DEFAULT_MEM_CACHE_ENABLED;

        /**
         * ?dir
         */
        public File diskCacheDir;

        /**
         * ??
         */
        public int diskCacheSize = DEFAULT_DISK_CACHE_SIZE;

        /**
         * @param context
         * @param uniqueName
         */
        public DataCacheParams(Context context, String uniqueName) {
            this.context = ContactsApp.getInstance();
            this.uniqueName = uniqueName;
        }

        public void setDiskCacheDir(File diskCacheDir) {
            this.diskCacheDir = diskCacheDir;
        }

        public int getMemoryClass() {
            return ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
        }
    }

    /**
     * A simple non-UI single Object that stores a single Object and is retained
     * over configuration changes. It will be used to retain the ImageCache
     * object.
     */
    public static class RetainCache {

        private static RetainCache instance;

        private Map<String, SoftReference<DataCache>> mRetainMap;

        /**
         * Private empty constructor as per the Object documentation
         */
        public RetainCache() {
        }

        /**
         * Get the stored object.
         * 
         * @return The stored object
         */
        public static synchronized RetainCache getInstance() {
            if (instance == null) {
                instance = new RetainCache();
            }
            return instance;
        }

        /**
         * Store a single object in this RetainObject.
         * 
         * @param object The object to store
         */
        public void setCache(String uniqueName, DataCache cache) {
            SoftReference<DataCache> mCachedObject = new SoftReference<DataCache>(cache);
            if (mRetainMap == null) {
                mRetainMap = new HashMap<String, SoftReference<DataCache>>();
            }
            mRetainMap.put(uniqueName, mCachedObject);
        }

        /**
         * Get the stored object.
         * 
         * @return The stored object
         */
        public Object getCache(String uniqueName) {
            if (mRetainMap != null) {
                SoftReference<DataCache> mCachedObject = mRetainMap.get(uniqueName);
                if (mCachedObject != null) {
                    return mCachedObject.get();
                }
            }
            return null;
        }

        /**
         * ?
         * 
         * @author wcy
         * @since 2015-5-15
         */
        public void clear() {
            if (mRetainMap != null) {
                mRetainMap.clear();
                mRetainMap = null;
            }
            instance = null;
        }
    }

}