aSimpleCache初识

来源:互联网 发布:mac os 系统修复 编辑:程序博客网 时间:2024/06/05 16:35

晚上家里来了一大堆东北亲戚,挺热闹的,生活嘛,肯定不只有写代码
aSimpleCache是一个缓存框架,中国人写的,一种莫名的亲切感,也是第一次使用,希望可以快速学习,对自己有一定的帮助。
github的链接
直接把那个ACache类拖入项目就可以简单的使用了
下面贴出来这个类的代码

package com.feng.asimplecachetest;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.PixelFormat;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import org.json.JSONArray;import org.json.JSONObject;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.io.RandomAccessFile;import java.io.Serializable;import java.util.Collections;import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;import java.util.Set;import java.util.concurrent.atomic.AtomicInteger;import java.util.concurrent.atomic.AtomicLong;/** * Created by hasee on 2017/6/12. */public class ACache {    public static final int TIME_HOUR = 60 * 60;    public static final int TIME_DAY = TIME_HOUR * 24;    private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb    private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量    private static Map<String, ACache> mInstanceMap = new HashMap<String, ACache>();    private ACacheManager mCache;    public static ACache get(Context ctx) {        return get(ctx, "ACache");    }    public static ACache get(Context ctx, String cacheName) {        File f = new File(ctx.getCacheDir(), cacheName);        return get(f, MAX_SIZE, MAX_COUNT);    }    public static ACache get(File cacheDir) {        return get(cacheDir, MAX_SIZE, MAX_COUNT);    }    public static ACache get(Context ctx, long max_zise, int max_count) {        File f = new File(ctx.getCacheDir(), "ACache");        return get(f, max_zise, max_count);    }    public static ACache get(File cacheDir, long max_zise, int max_count) {        ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());        if (manager == null) {            manager = new ACache(cacheDir, max_zise, max_count);            mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);        }        return manager;    }    private static String myPid() {        return "_" + android.os.Process.myPid();    }    private ACache(File cacheDir, long max_size, int max_count) {        if (!cacheDir.exists() && !cacheDir.mkdirs()) {            throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath());        }        mCache = new ACacheManager(cacheDir, max_size, max_count);    }    /**     * Provides a means to save a cached file before the data are available.     * Since writing about the file is complete, and its close method is called,     * its contents will be registered in the cache. Example of use:     *     * ACache cache = new ACache(this) try { OutputStream stream =     * cache.put("myFileName") stream.write("some bytes".getBytes()); // now     * update cache! stream.close(); } catch(FileNotFoundException e){     * e.printStackTrace() }     */    class xFileOutputStream extends FileOutputStream {        File file;        public xFileOutputStream(File file) throws FileNotFoundException {            super(file);            this.file = file;        }        public void close() throws IOException {            super.close();            mCache.put(file);        }    }// =======================================// ============ String数据 读写 ==============// =======================================    /**     * 保存 String数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的String数据     */    public void put(String key, String value) {        File file = mCache.newFile(key);        BufferedWriter out = null;        try {            out = new BufferedWriter(new FileWriter(file), 1024);            out.write(value);        } catch (IOException e) {            e.printStackTrace();        } finally {            if (out != null) {                try {                    out.flush();                    out.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            mCache.put(file);        }    }    /**     * 保存 String数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的String数据     * @param saveTime     *            保存的时间,单位:秒     */    public void put(String key, String value, int saveTime) {        put(key, Utils.newStringWithDateInfo(saveTime, value));    }    /**     * 读取 String数据     *     * @param key     * @return String 数据     */    public String getAsString(String key) {        File file = mCache.get(key);        if (!file.exists())            return null;        boolean removeFile = false;        BufferedReader in = null;        try {            in = new BufferedReader(new FileReader(file));            String readString = "";            String currentLine;            while ((currentLine = in.readLine()) != null) {                readString += currentLine;            }            if (!Utils.isDue(readString)) {                return Utils.clearDateInfo(readString);            } else {                removeFile = true;                return null;            }        } catch (IOException e) {            e.printStackTrace();            return null;        } finally {            if (in != null) {                try {                    in.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if (removeFile)                remove(key);        }    }// =======================================// ============= JSONObject 数据 读写 ==============// =======================================    /**     * 保存 JSONObject数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的JSON数据     */    public void put(String key, JSONObject value) {        put(key, value.toString());    }    /**     * 保存 JSONObject数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的JSONObject数据     * @param saveTime     *            保存的时间,单位:秒     */    public void put(String key, JSONObject value, int saveTime) {        put(key, value.toString(), saveTime);    }    /**     * 读取JSONObject数据     *     * @param key     * @return JSONObject数据     */    public JSONObject getAsJSONObject(String key) {        String JSONString = getAsString(key);        try {            JSONObject obj = new JSONObject(JSONString);            return obj;        } catch (Exception e) {            e.printStackTrace();            return null;        }    }// =======================================// ============ JSONArray 数据 读写 =============// =======================================    /**     * 保存 JSONArray数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的JSONArray数据     */    public void put(String key, JSONArray value) {        put(key, value.toString());    }    /**     * 保存 JSONArray数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的JSONArray数据     * @param saveTime     *            保存的时间,单位:秒     */    public void put(String key, JSONArray value, int saveTime) {        put(key, value.toString(), saveTime);    }    /**     * 读取JSONArray数据     *     * @param key     * @return JSONArray数据     */    public JSONArray getAsJSONArray(String key) {        String JSONString = getAsString(key);        try {            JSONArray obj = new JSONArray(JSONString);            return obj;        } catch (Exception e) {            e.printStackTrace();            return null;        }    }// =======================================// ============== byte 数据 读写 =============// =======================================    /**     * 保存 byte数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的数据     */    public void put(String key, byte[] value) {        File file = mCache.newFile(key);        FileOutputStream out = null;        try {            out = new FileOutputStream(file);            out.write(value);        } catch (Exception e) {            e.printStackTrace();        } finally {            if (out != null) {                try {                    out.flush();                    out.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            mCache.put(file);        }    }    /**     * Cache for a stream     *     * @param key     *            the file name.     * @return OutputStream stream for writing data.     * @throws FileNotFoundException     *             if the file can not be created.     */    public OutputStream put(String key) throws FileNotFoundException {        return new xFileOutputStream(mCache.newFile(key));    }    /**     *     * @param key     *            the file name.     * @return (InputStream or null) stream previously saved in cache.     * @throws FileNotFoundException     *             if the file can not be opened     */    public InputStream get(String key) throws FileNotFoundException {        File file = mCache.get(key);        if (!file.exists())            return null;        return new FileInputStream(file);    }    /**     * 保存 byte数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的数据     * @param saveTime     *            保存的时间,单位:秒     */    public void put(String key, byte[] value, int saveTime) {        put(key, Utils.newByteArrayWithDateInfo(saveTime, value));    }    /**     * 获取 byte 数据     *     * @param key     * @return byte 数据     */    public byte[] getAsBinary(String key) {        RandomAccessFile RAFile = null;        boolean removeFile = false;        try {            File file = mCache.get(key);            if (!file.exists())                return null;            RAFile = new RandomAccessFile(file, "r");            byte[] byteArray = new byte[(int) RAFile.length()];            RAFile.read(byteArray);            if (!Utils.isDue(byteArray)) {                return Utils.clearDateInfo(byteArray);            } else {                removeFile = true;                return null;            }        } catch (Exception e) {            e.printStackTrace();            return null;        } finally {            if (RAFile != null) {                try {                    RAFile.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if (removeFile)                remove(key);        }    }// =======================================// ============= 序列化 数据 读写 ===============// =======================================    /**     * 保存 Serializable数据 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的value     */    public void put(String key, Serializable value) {        put(key, value, -1);    }    /**     * 保存 Serializable数据到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的value     * @param saveTime     *            保存的时间,单位:秒     */    public void put(String key, Serializable value, int saveTime) {        ByteArrayOutputStream baos = null;        ObjectOutputStream oos = null;        try {            baos = new ByteArrayOutputStream();            oos = new ObjectOutputStream(baos);            oos.writeObject(value);            byte[] data = baos.toByteArray();            if (saveTime != -1) {                put(key, data, saveTime);            } else {                put(key, data);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                oos.close();            } catch (IOException e) {            }        }    }    /**     * 读取 Serializable数据     *     * @param key     * @return Serializable 数据     */    public Object getAsObject(String key) {        byte[] data = getAsBinary(key);        if (data != null) {            ByteArrayInputStream bais = null;            ObjectInputStream ois = null;            try {                bais = new ByteArrayInputStream(data);                ois = new ObjectInputStream(bais);                Object reObject = ois.readObject();                return reObject;            } catch (Exception e) {                e.printStackTrace();                return null;            } finally {                try {                    if (bais != null)                        bais.close();                } catch (IOException e) {                    e.printStackTrace();                }                try {                    if (ois != null)                        ois.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }        return null;    }// =======================================// ============== bitmap 数据 读写 =============// =======================================    /**     * 保存 bitmap 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的bitmap数据     */    public void put(String key, Bitmap value) {        put(key, Utils.Bitmap2Bytes(value));    }    /**     * 保存 bitmap 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的 bitmap 数据     * @param saveTime     *            保存的时间,单位:秒     */    public void put(String key, Bitmap value, int saveTime) {        put(key, Utils.Bitmap2Bytes(value), saveTime);    }    /**     * 读取 bitmap 数据     *     * @param key     * @return bitmap 数据     */    public Bitmap getAsBitmap(String key) {        if (getAsBinary(key) == null) {            return null;        }        return Utils.Bytes2Bimap(getAsBinary(key));    }// =======================================// ============= drawable 数据 读写 =============// =======================================    /**     * 保存 drawable 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的drawable数据     */    public void put(String key, Drawable value) {        put(key, Utils.drawable2Bitmap(value));    }    /**     * 保存 drawable 到 缓存中     *     * @param key     *            保存的key     * @param value     *            保存的 drawable 数据     * @param saveTime     *            保存的时间,单位:秒     */    public void put(String key, Drawable value, int saveTime) {        put(key, Utils.drawable2Bitmap(value), saveTime);    }    /**     * 读取 Drawable 数据     *     * @param key     * @return Drawable 数据     */    public Drawable getAsDrawable(String key) {        if (getAsBinary(key) == null) {            return null;        }        return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key)));    }    /**     * 获取缓存文件     *     * @param key     * @return value 缓存的文件     */    public File file(String key) {        File f = mCache.newFile(key);        if (f.exists())            return f;        return null;    }    /**     * 移除某个key     *     * @param key     * @return 是否移除成功     */    public boolean remove(String key) {        return mCache.remove(key);    }    /**     * 清除所有数据     */    public void clear() {        mCache.clear();    }    /**     * @title 缓存管理器     * @author 杨福海(michael) www.yangfuhai.com     * @version 1.0     */    public class ACacheManager {        private final AtomicLong cacheSize;        private final AtomicInteger cacheCount;        private final long sizeLimit;        private final int countLimit;        private final Map<File, Long> lastUsageDates = Collections.synchronizedMap(new HashMap<File, Long>());        protected File cacheDir;        private ACacheManager(File cacheDir, long sizeLimit, int countLimit) {            this.cacheDir = cacheDir;            this.sizeLimit = sizeLimit;            this.countLimit = countLimit;            cacheSize = new AtomicLong();            cacheCount = new AtomicInteger();            calculateCacheSizeAndCacheCount();        }        /**         * 计算 cacheSize和cacheCount         */        private void calculateCacheSizeAndCacheCount() {            new Thread(new Runnable() {                @Override                public void run() {                    int size = 0;                    int count = 0;                    File[] cachedFiles = cacheDir.listFiles();                    if (cachedFiles != null) {                        for (File cachedFile : cachedFiles) {                            size += calculateSize(cachedFile);                            count += 1;                            lastUsageDates.put(cachedFile, cachedFile.lastModified());                        }                        cacheSize.set(size);                        cacheCount.set(count);                    }                }            }).start();        }        private void put(File file) {            int curCacheCount = cacheCount.get();            while (curCacheCount + 1 > countLimit) {                long freedSize = removeNext();                cacheSize.addAndGet(-freedSize);                curCacheCount = cacheCount.addAndGet(-1);            }            cacheCount.addAndGet(1);            long valueSize = calculateSize(file);            long curCacheSize = cacheSize.get();            while (curCacheSize + valueSize > sizeLimit) {                long freedSize = removeNext();                curCacheSize = cacheSize.addAndGet(-freedSize);            }            cacheSize.addAndGet(valueSize);            Long currentTime = System.currentTimeMillis();            file.setLastModified(currentTime);            lastUsageDates.put(file, currentTime);        }        private File get(String key) {            File file = newFile(key);            Long currentTime = System.currentTimeMillis();            file.setLastModified(currentTime);            lastUsageDates.put(file, currentTime);            return file;        }        private File newFile(String key) {            return new File(cacheDir, key.hashCode() + "");        }        private boolean remove(String key) {            File image = get(key);            return image.delete();        }        private void clear() {            lastUsageDates.clear();            cacheSize.set(0);            File[] files = cacheDir.listFiles();            if (files != null) {                for (File f : files) {                    f.delete();                }            }        }        /**         * 移除旧的文件         *         * @return         */        private long removeNext() {            if (lastUsageDates.isEmpty()) {                return 0;            }            Long oldestUsage = null;            File mostLongUsedFile = null;            Set<Entry<File, Long>> entries = lastUsageDates.entrySet();            synchronized (lastUsageDates) {                for (Entry<File, Long> entry : entries) {                    if (mostLongUsedFile == null) {                        mostLongUsedFile = entry.getKey();                        oldestUsage = entry.getValue();                    } else {                        Long lastValueUsage = entry.getValue();                        if (lastValueUsage < oldestUsage) {                            oldestUsage = lastValueUsage;                            mostLongUsedFile = entry.getKey();                        }                    }                }            }            long fileSize = calculateSize(mostLongUsedFile);            if (mostLongUsedFile.delete()) {                lastUsageDates.remove(mostLongUsedFile);            }            return fileSize;        }        private long calculateSize(File file) {            return file.length();        }    }    /**     * @title 时间计算工具类     * @author 杨福海(michael) www.yangfuhai.com     * @version 1.0     */    private static class Utils {        /**         * 判断缓存的String数据是否到期         *         * @param str         * @return true:到期了 false:还没有到期         */        private static boolean isDue(String str) {            return isDue(str.getBytes());        }        /**         * 判断缓存的byte数据是否到期         *         * @param data         * @return true:到期了 false:还没有到期         */        private static boolean isDue(byte[] data) {            String[] strs = getDateInfoFromDate(data);            if (strs != null && strs.length == 2) {                String saveTimeStr = strs[0];                while (saveTimeStr.startsWith("0")) {                    saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length());                }                long saveTime = Long.valueOf(saveTimeStr);                long deleteAfter = Long.valueOf(strs[1]);                if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) {                    return true;                }            }            return false;        }        private static String newStringWithDateInfo(int second, String strInfo) {            return createDateInfo(second) + strInfo;        }        private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) {            byte[] data1 = createDateInfo(second).getBytes();            byte[] retdata = new byte[data1.length + data2.length];            System.arraycopy(data1, 0, retdata, 0, data1.length);            System.arraycopy(data2, 0, retdata, data1.length, data2.length);            return retdata;        }        private static String clearDateInfo(String strInfo) {            if (strInfo != null && hasDateInfo(strInfo.getBytes())) {                strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length());            }            return strInfo;        }        private static byte[] clearDateInfo(byte[] data) {            if (hasDateInfo(data)) {                return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length);            }            return data;        }        private static boolean hasDateInfo(byte[] data) {            return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14;        }        private static String[] getDateInfoFromDate(byte[] data) {            if (hasDateInfo(data)) {                String saveDate = new String(copyOfRange(data, 0, 13));                String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator)));                return new String[] { saveDate, deleteAfter };            }            return null;        }        private static int indexOf(byte[] data, char c) {            for (int i = 0; i < data.length; i++) {                if (data[i] == c) {                    return i;                }            }            return -1;        }        private static byte[] copyOfRange(byte[] original, int from, int to) {            int newLength = to - from;            if (newLength < 0)                throw new IllegalArgumentException(from + " > " + to);            byte[] copy = new byte[newLength];            System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));            return copy;        }        private static final char mSeparator = ' ';        private static String createDateInfo(int second) {            String currentTime = System.currentTimeMillis() + "";            while (currentTime.length() < 13) {                currentTime = "0" + currentTime;            }            return currentTime + "-" + second + mSeparator;        }        /*        * Bitmap → byte[]        */        private static byte[] Bitmap2Bytes(Bitmap bm) {            if (bm == null) {                return null;            }            ByteArrayOutputStream baos = new ByteArrayOutputStream();            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);            return baos.toByteArray();        }        /*        * byte[] → Bitmap        */        private static Bitmap Bytes2Bimap(byte[] b) {            if (b.length == 0) {                return null;            }            return BitmapFactory.decodeByteArray(b, 0, b.length);        }        /*        * Drawable → Bitmap        */        private static Bitmap drawable2Bitmap(Drawable drawable) {            if (drawable == null) {                return null;            }// 取 drawable 的长宽            int w = drawable.getIntrinsicWidth();            int h = drawable.getIntrinsicHeight();// 取 drawable 的颜色格式            Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;// 建立对应 bitmap            Bitmap bitmap = Bitmap.createBitmap(w, h, config);// 建立对应 bitmap 的画布            Canvas canvas = new Canvas(bitmap);            drawable.setBounds(0, 0, w, h);// 把 drawable 内容画到画布中            drawable.draw(canvas);            return bitmap;        }        /*        * Bitmap → Drawable        */        @SuppressWarnings("deprecation")        private static Drawable bitmap2Drawable(Bitmap bm) {            if (bm == null) {                return null;            }            BitmapDrawable bd=new BitmapDrawable(bm);            bd.setTargetDensity(bm.getDensity());            return new BitmapDrawable(bm);        }    }}

有时间会分析下代码,完成一个简单的demo

public class MainActivity extends Activity {    private Button save_data;    private  Button restore_data;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        save_data=(Button)findViewById(R.id.save_data);        restore_data=(Button)findViewById(R.id.restore_data);        save_data.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                ACache mCache = ACache.get(MainActivity.this);                mCache.put("test_key1", "齐晨");                mCache.put("test_key2", "齐晨", 10);//保存10秒,如果超过10秒去获取这个key,将为null                mCache.put("test_key3", "test value", 2 * ACache.TIME_DAY);//保存两天,如果超过两天去获取这个key,将为null            }        });        restore_data.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                ACache mCache = ACache.get(MainActivity.this);                String value = mCache.getAsString("test_key2");                Log.i("MainActivity",value+"");            }        });    }}

测试缓存存储,并且10S后删除缓存数据
这里写图片描述
简单的实现了功能,深入学习的会补充

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 儿子发烧39度该怎么办 孩子发烧39度7怎么办 7个月婴儿发烧怎么办 感冒了头发很油怎么办 5岁宝宝发烧39度怎么办 婴儿烧到39.5度怎么办 1岁多宝宝39.5度怎么办 宝宝发烧40多度怎么办 7岁宝宝发烧了怎么办 宝宝反复发烧39度怎么办 一岁半宝宝反复发烧39度怎么办 七岁发烧38度怎么办 小孩一直37度1怎么办 婴儿一直37度多怎么办 1岁半高烧39度怎么办 反复发烧39度多怎么办 孩子不爱喝水怎么办%3f 8岁儿童不爱喝水怎么办 儿子14岁了不爱说话怎么办 我孩子长得老慢怎么办 老公嫌你烦了怎么办 2岁宝宝吃饭不嚼怎么办 2岁宝宝挑食厌食怎么办 孩子不爱和家长交流怎么办 孩子发烧在医院查不出病因怎么办 宝宝乳牙长歪了怎么办 两岁宝宝不爱吃水果怎么办 两岁宝宝不吃水果怎么办 一岁的宝宝上火了怎么办 吃水果嘴唇肿了怎么办 二岁宝宝不爱吃饭怎么办 小婴儿便秘但不爱喝水怎么办 宝宝只吃水果不吃饭怎么办 一岁宝宝不喜欢吃水果怎么办 1岁宝宝不吃水果怎么办 一岁半宝宝吃水果拉肚子怎么办 大人发烧了怎么办如何退烧 怀孕后不爱吃水果怎么办 不敢吃水果了怕虫怎么办 宝宝发烧38度不出汗怎么办 1岁宝宝喜欢含饭怎么办