精华内容
下载资源
问答
  • 内存虚拟磁盘缓存工具 虚拟磁盘缓存后大大提升硬盘性能 加快存取速度
  • Glide 缓存工具例子,缓存大小获取,磁盘缓存清除(2 种方法),内存缓存清除

    GlideCatchSimple

    项目地址: YaphetZhao/GlideCatchSimple
    简介:Glide 缓存工具例子,缓存大小获取,磁盘缓存清除(2 种方法),内存缓存清除
    更多: 作者    提 Bug   
    标签:
    Glide-

    Glide 缓存 Simple

    1. 缓存路径的指定
    2. 缓存大小的获取
    3. 磁盘缓存清除(两种方法)
    4. 内存缓存清除

    5. 可 clone 之后查看使用 Simple

    Glide cache Simple.

    1. The cache path specified
    2. The cache size
    3. The disk cache (two ways)
    4. Memory cache to clearMay

    5. use Simple clone after check

    GlideCatchUtil

    获取 Glide 磁盘缓存大小

    public String getCacheSize() {
        try {
            return getFormatSize(getFolderSize(new File(Application.getInstance().getCacheDir() + "/" + GlideCatchConfig.GLIDE_CARCH_DIR)));
        } catch (Exception e) {
            e.printStackTrace();
            return "获取失败";
        }
    }
    

    清除 Glide 磁盘缓存

    public boolean cleanCatchDisk() {
        return deleteFolderFile(Application.getInstance().getCacheDir() + "/" + GlideCatchConfig.GLIDE_CARCH_DIR, true);
    }
    
    public boolean clearCacheDiskSelf() {
        try {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Glide.get(Application.getInstance()).clearDiskCache();
                    }
                }).start();
            } else {
                Glide.get(Application.getInstance()).clearDiskCache();
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    

    AndroidMainfest.xml and GlideConfiguration.class

    <meta-data
        android:name="com.yaphetzhao.glidecatchsimple.glide.GlideConfiguration"
        android:value="GlideModule" />
    

    Application.class

    public class Application extends android.app.Application {
    
        public static Application instance;
    
        public static Application getInstance() {
            return instance;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            instance = this;
        }
    
    }
    
    <application
        android:name=".Application"
        more...
    

    About Me

    YaphetZhao Email:yaphetzhao@gmail.com Email_CN:yaphetzhao@foxmail.com GitHub:http://github.com/YaphetZhao/ QQ:11613371 CSDN_Blog:http://blog.csdn.net/yaphetzhao

    展开全文
  • 工具可以将固态硬盘内存作为机械硬盘缓存,从而提升固态硬盘响应速度,绿色无毒,亲测可用,
  • 如果是在DOS下,则应在autoexec.bat 文件中加入一行“LH C:\dos\smartdrv.exe”(这里假设smartdrv 程序在C:\dos 目录下),即可实现内存作为硬盘缓存。 如果您想使其成为光驱的 缓存,只要把autoexec.bat中的执行...
  • 基与LruCache(内存缓存)和 DiskLruCache(硬盘缓存)的图片三级缓存工具类,方便好用
  • 1. 添加依赖,在AndroidManifest.xml全局化配置:  compile '... 自己建立一个工具类: import com.facebook.drawee.backends.pipeline.Fresco; //全局初始化Application类 public class

    1. 添加依赖,在AndroidManifest.xml清单文件中配置:    

    compile 'com.facebook.fresco:fresco:1.5.0'


    <application
        android:name=".util.BaseApplication"
                

    2. 全局初始化配置 Fresco :       

    import android.app.Application;
    import com.facebook.drawee.backends.pipeline.Fresco;
    
    //全局初始化Application类
    public class BaseApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate(); 
    
            //用于全局配置初始化Fresco 图片加载
            Fresco.initialize(this,Fresco_ImagePipelineConfigUtil.getDefaultImagePipelineConfig(this));
        }
    
    }      


    3. 工具类:

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.os.Environment;
    import android.util.Log;
    import com.facebook.cache.disk.DiskCacheConfig;
    import com.facebook.common.disk.NoOpDiskTrimmableRegistry;
    import com.facebook.common.internal.Supplier;
    import com.facebook.common.memory.MemoryTrimType;
    import com.facebook.common.memory.MemoryTrimmable;
    import com.facebook.common.memory.NoOpMemoryTrimmableRegistry;
    import com.facebook.common.util.ByteConstants;
    import com.facebook.imagepipeline.cache.MemoryCacheParams;
    import com.facebook.imagepipeline.core.ImagePipelineConfig;
    import com.facebook.imagepipeline.core.ImagePipelineFactory;
    
    /**
     * Fresco磁盘缓存工具类
     */
    public class Fresco_ImagePipelineConfigUtil {
        //分配的可用内存
        private static final int MAX_HEAP_SIZE = (int) Runtime.getRuntime().maxMemory();
        //使用的缓存数量
        private static final int MAX_MEMORY_CACHE_SIZE = MAX_HEAP_SIZE / 4;
        //小图极低磁盘空间缓存的最大值(特性:可将大量的小图放到额外放在另一个磁盘空间防止大图占用磁盘空间而删除了大量的小图)
        private static final int MAX_SMALL_DISK_VERYLOW_CACHE_SIZE = 20 * ByteConstants.MB;
        //小图低磁盘空间缓存的最大值(特性:可将大量的小图放到额外放在另一个磁盘空间防止大图占用磁盘空间而删除了大量的小图)
        private static final int MAX_SMALL_DISK_LOW_CACHE_SIZE = 60 * ByteConstants.MB;
        //默认图极低磁盘空间缓存的最大值
        private static final int MAX_DISK_CACHE_VERYLOW_SIZE = 20 * ByteConstants.MB;
        //默认图低磁盘空间缓存的最大值
        private static final int MAX_DISK_CACHE_LOW_SIZE = 60 * ByteConstants.MB;
        //默认图磁盘缓存的最大值
        private static final int MAX_DISK_CACHE_SIZE = 100 * ByteConstants.MB;
        //小图所放路径的文件夹名
        private static final String IMAGE_PIPELINE_SMALL_CACHE_DIR = "ImagePipelineCacheSmall";
        //默认图所放路径的文件夹名
        private static final String IMAGE_PIPELINE_CACHE_DIR = "ImagePipelineCacheDefault";
    
        //ImagePipelineConfig 的完整配置
        public static ImagePipelineConfig getDefaultImagePipelineConfig(Context context) {
    
            //内存配置
            final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams(
                    MAX_MEMORY_CACHE_SIZE,// 内存缓存中总图片的最大大小,以字节为单位。
                    Integer.MAX_VALUE,// 内存缓存中图片的最大数量。
                    MAX_MEMORY_CACHE_SIZE,// 内存缓存中准备清除但尚未被删除的总图片的最大大小,以字节为单位。
                    Integer.MAX_VALUE,// 内存缓存中准备清除的总图片的最大数量。
                    Integer.MAX_VALUE);// 内存缓存中单个图片的最大大小。
    
            //修改内存图片缓存数量,空间策略(这个方式有点恶心)
            Supplier<MemoryCacheParams> mSupplierMemoryCacheParams = new Supplier<MemoryCacheParams>() {
                @Override
                public MemoryCacheParams get() {
                    return bitmapCacheParams;
                }
    
            };
    
    
            //小图片的磁盘配置
            DiskCacheConfig diskSmallCacheConfig = DiskCacheConfig.newBuilder(context).setBaseDirectoryPath(context.getApplicationContext().getCacheDir())//缓存图片基路径
                    .setBaseDirectoryName(IMAGE_PIPELINE_SMALL_CACHE_DIR)//文件夹名
                    .setMaxCacheSize(MAX_DISK_CACHE_SIZE)//默认缓存的最大大小。
                    .setMaxCacheSizeOnLowDiskSpace(MAX_SMALL_DISK_LOW_CACHE_SIZE)//缓存的最大大小,使用设备时低磁盘空间。
                    .setMaxCacheSizeOnVeryLowDiskSpace(MAX_SMALL_DISK_VERYLOW_CACHE_SIZE)//缓存的最大大小,当设备极低磁盘空间
                    .setDiskTrimmableRegistry(NoOpDiskTrimmableRegistry.getInstance())
                    .build();
    
            //默认图片的磁盘配置
            DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(context).setBaseDirectoryPath(Environment.getExternalStorageDirectory().getAbsoluteFile())//缓存图片基路径
                    .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR)//文件夹名
                    .setMaxCacheSize(MAX_DISK_CACHE_SIZE)//默认缓存的最大大小。
                    .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_CACHE_LOW_SIZE)//缓存的最大大小,使用设备时低磁盘空间。
                    .setMaxCacheSizeOnVeryLowDiskSpace(MAX_DISK_CACHE_VERYLOW_SIZE)//缓存的最大大小,当设备极低磁盘空间
                    .setDiskTrimmableRegistry(NoOpDiskTrimmableRegistry.getInstance())
                    .build();
    
            //缓存图片配置
            ImagePipelineConfig.Builder configBuilder = ImagePipelineConfig.newBuilder(context)
                    .setBitmapsConfig(Bitmap.Config.RGB_565)
                    .setBitmapMemoryCacheParamsSupplier(mSupplierMemoryCacheParams)
                    .setSmallImageDiskCacheConfig(diskSmallCacheConfig)
                    .setMainDiskCacheConfig(diskCacheConfig)
                    .setMemoryTrimmableRegistry(NoOpMemoryTrimmableRegistry.getInstance())
                    .setResizeAndRotateEnabledForNetwork(true);
    
            // 这段代码,用于清理缓存
            NoOpMemoryTrimmableRegistry.getInstance().registerMemoryTrimmable(new MemoryTrimmable() {
                @Override
                public void trim(MemoryTrimType trimType) {
                    final double suggestedTrimRatio = trimType.getSuggestedTrimRatio();
                    String log = String.format("onCreate suggestedTrimRatio : %d", suggestedTrimRatio);
                    Log.d("Fresco缓存",log);
                    if (MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio() == suggestedTrimRatio
                            || MemoryTrimType.OnSystemLowMemoryWhileAppInBackground.getSuggestedTrimRatio() == suggestedTrimRatio
                            || MemoryTrimType.OnSystemLowMemoryWhileAppInForeground.getSuggestedTrimRatio() == suggestedTrimRatio
                            ) {
                        ImagePipelineFactory.getInstance().getImagePipeline().clearMemoryCaches();
                    }
                }
            });
            return configBuilder.build();
        }
    
    }

    展开全文
  • SSD硬盘缓存工具

    2018-07-25 21:00:55
    可用于win7 X64系统SSD硬盘缓存设置,首先需装有SSD硬盘
  • DiskDataCacher磁盘缓存工具用法以及原理原创文档,转载请注明出处 by WindyDiskDataCacher是一个轻量级的Android磁盘缓存工具,基于LRU算法实现,同时可以设置缓存有效期,使用起来十分方便。 源码:...

    DiskDataCacher磁盘缓存工具用法以及原理

    原创文档,转载请注明出处 by Windy

    DiskDataCacher是一个轻量级的Android磁盘缓存工具,基于LRU算法实现,同时可以设置缓存有效期,使用起来十分方便。
    源码:DiskDataCacher

    工具用途

    • 用于缓存网络请求返回的数据,并且可以设置缓存数据的有效期,比如,缓存时间假设为1个小时,超时1小时后再次获取缓存会自动失效,让客户端重新请求新的数据,这样可以减少客户端流量,同时减少服务器并发量。
    • 用于代替SharePreference当做配置文件,缓存一些较大的配置数据,效率更高,可以减少内存消耗。SharePreference 不能用来缓存较大数据的理由:请不要滥用SharedPreference
    • 支持扩展,扩展后可以缓存JsonObjectBitmapDrawable和序列化的java对象等等。

    对比ASimpleCacheDiskLruCache

     跟ASimpleCache比较,优点主要有:

    • 两者都是给予LRU(最近最少使用)算法,但ASimpleCache是使用HashMap实现lru,而DiskDataCacher是使用排序好的LinkedHashMap实现lru算法,查询过期数据的效率更高;
    • DiskDataCacher对线程同步的支持更好;
    • DiskDataCacher封装了线程池,支持异步存取。

     跟DiskLruCache比较,优点主要有:

    • DiskDataCacher支持设置缓存数据的有效期,再次获取超期数据会自动清除
    • DiskDataCacher实现方式更简单,使用更轻量,并不需要一个journal文件记录数据操作情况

    用法简介

    DiskStringCacheManager,封装了DiskDataCacher,是专门用来缓存字符串的工具,是单例模式,一般在Application的onCreate中进行初始化:

        @Override
        public void onCreate() {
            super.onCreate();
            DiskStringCacheManager.init(new File(getCacheDir(), DiskStringCacheManager.DEFAULT_CACHE_FILE_NAME),
                    DiskStringCacheManager.MAX_CACHE_SIZE);
        }

    保存数据:

    
        String cacheStringValue = "多线程比多任务更加有挑战。多线程是在同一个程序内部并行执行,\n";
        long maxTime = 3 * 60 * 1000;   //缓存有效期3分钟
        DiskStringCacheManager.get().putAsync(cacheKey, cacheStringValue);   //异步方式缓存, 缓存数据一直有效
        DiskStringCacheManager.get().putAsync(cacheKey, cacheStringValue, maxTime);  //异步方式缓存, 缓存数据一直有效期为3分钟
        DiskStringCacheManager.get().put(cacheKey, cacheStringValue, maxTime);   //同步方式缓存

    获取数据:

        //异步方式获取
        DiskStringCacheManager.get().getAsync(cacheKey, new WeakReference<DiskStringCacheManager.Callback>(new DiskStringCacheManager.Callback() {
                    @Override
                    public void actionDone(final String result) {
                        if (!TextUtils.isEmpty(result)) {
                            textView.setText(result);
                        }
                    }
                }));
        //同步方式获取
        String result = DiskStringCacheManager.get().get(cacheKey);

    源码剖析

    初始化方法实现思路:

    初始化时,遍历缓存目录下的所有缓存文件,并读取出文件起始段的信息,此信息包含缓存文件大小,缓存有效期,缓存的键值,并将这些信息和缓存文件上次修改时间(LastModifiedTime)存到一个List中,然后将此list根据文件上次修改时间进行排序,排序好后,存到全局变量LinkedHashMap mCacheInfoMap中,这个map用于LRU算法获取缓存,具体的初始化实现如下:

            ...
            ...
          //先存到list中进行排序,然后再存到mCacheInfoMap中
            List<CacheInfoWithModifiedTime> cacheInfoSortList = null;
            try {
                File[] fileList = mRootDirectory.listFiles();
                cacheInfoSortList = new ArrayList<>(fileList.length); //设置初始化大小,避免扩容
    
                for (File file : fileList) {
                    BufferedInputStream fis = null;
                    try {
                        fis = new BufferedInputStream(new FileInputStream(file));
                        CacheInfo info = CacheInfo.readCacheInfo(fis);
                        info.size = file.length();
                        //初始化时,遇到过期的数据,需要清除掉
                        if (info.isExpiredCache()) {
                            file.delete();
                            continue;
                        }
                        long fileLastModifiedTime = file.lastModified();
                        CacheInfoWithModifiedTime infoWithModifiedTime = new CacheInfoWithModifiedTime(info, fileLastModifiedTime);
                        cacheInfoSortList.add(infoWithModifiedTime);
                    } catch (Exception e) {
                        ...
                    } finally {
                        ...
                    }
                }
            } finally {
                if (cacheInfoSortList != null && cacheInfoSortList.size() != 0) {
                    //对文件中取到的CacheInfo按照时间排序,用以实现最近最少原则
                    Collections.sort(cacheInfoSortList, new FileModifiedTimeComparator());
                    for (CacheInfoWithModifiedTime infoWithModifiedTime : cacheInfoSortList) {
                        putCacheInfo(infoWithModifiedTime.info.key, infoWithModifiedTime.info);
                    }
                }
                synchronized (mLock) {
                    mInitialized = true;
                    mLock.notifyAll();
                }
            }

    get方法实现思路:

    先根据key从mCacheInfoMap中取缓存信息(mCacheInfoMap是一个LinkedHashMap,调用其get方法后,这个键值对就会添加到链表尾部成为最新的元素,以此实现LRU),然后根据key获取缓存文件名,从缓存文件中读取缓存内容,并将内容返回,以此实现get方法:

        @Override
        public Entry get(String key) {
            synchronized (mLock) {
                awaitInitializeLocked();
                //LinkedHashMap get之后,会将此键值对移到链表尾部,以实现LRU
                CacheInfo info = mCacheInfoMap.get(key); 
                File cachedFile = getFileForKey(key);
                //缓存文件不存在
                if (!cachedFile.exists()) {
                    removeCacheInfo(key);
                    return null;
                }
                //缓存的数据已经过期
                if (info != null && info.isExpiredCache()) {
                    removeCacheInfo(key);
                    cachedFile.delete();
                    return null;
                }
                CountingInputStream cis = null;
                try {
                    cis = new CountingInputStream(new BufferedInputStream(new FileInputStream(cachedFile)));
                    CacheInfo fileInfo = CacheInfo.readCacheInfo(cis);
                    fileInfo.size = cachedFile.length();
                    //设置时间为了初始化时排序
                    cachedFile.setLastModified(System.currentTimeMillis());   
                    if (info == null || !info.equals(fileInfo)) {   //一般不会出现这种情况
                        info = fileInfo;
                        mCacheInfoMap.put(key, info);
                    }
                    byte[] data = StreamUtils.streamToBytes(cis, (int) (cachedFile.length() - cis.bytesRead));
                    return info.toCacheEntry(data);
                } catch (Exception e) {
                    e.printStackTrace();
                    remove(key);
                } finally {
                    ...
                }
                return null;
            }
        }

    put方法实现思路:

    存储数据之前,需要先判断存储数据到本地磁盘后,是否会超出允许的最大存阈值,即mMaxCacheSizeInBytes,超出的话,就先遍历mCacheInfoMap一遍,删除所有的过期数据,再次判断是否超出最大阈值mMaxCacheSizeInBytes,超出的话,删除mCacheInfoMap中最老的数据,直到不再超出阈值,具体代码如下:

        private void trimToMaxSize(int neededSpace) {
            if (mTotalSize + neededSpace < mMaxCacheSizeInBytes) {
                return;
            }
            //先删除所有的过期数据
            Iterator<Map.Entry<String, CacheInfo>> iterator = mCacheInfoMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, CacheInfo> entry = iterator.next();
                String key = entry.getKey();
                CacheInfo info = entry.getValue();
                if (info.isExpiredCache()) {
                    File file = getFileForKey(key);
                    boolean deleted = file.delete();
                    if (deleted) {
                        mTotalSize -= info.size;
                    } else {
                    }
                    iterator.remove();
                }
            }
            if (mTotalSize + neededSpace <= mMaxCacheSizeInBytes) {
                return;
            }
            //再根据Lru算法删除最老的数据,直到不超过阈值
            Iterator<Map.Entry<String, CacheInfo>> iterator2 = mCacheInfoMap.entrySet().iterator();
            while (iterator2.hasNext()) {
                Map.Entry<String, CacheInfo> entry = iterator2.next();
                String key = entry.getKey();
                CacheInfo info = entry.getValue();
                File file = getFileForKey(key);
                boolean deleted = file.delete();
                if (deleted) {
                    mTotalSize -= info.size;
                } else { 
                }
                iterator2.remove();
                if (mTotalSize + neededSpace < mMaxCacheSizeInBytes * DEFAULT_LOAD_FACTOR) {
                    break;
                }
            }
        }

    判断完成之后,就将需要存储的数据信息(CacheInfo)和数据详细内容(entry.data)依次存储到文件中:

    @Override
        public void put(String key, Entry entry) {
            synchronized (mLock) {
                awaitInitializeLocked();
                trimToMaxSize(entry.data.length);
                File file = getFileForKey(key);
                BufferedOutputStream fos = null;
                try {
                    fos = new BufferedOutputStream(new FileOutputStream(file));
                    CacheInfo info = new CacheInfo(key, entry);  //创建CacheInfo
                    boolean success = info.writeCacheInfo(fos);   //将CacheInfo信息写入到文件前面
                    if (!success) {
                        return;
                    }
                    fos.write(entry.data);   //将data数据写入到文件后面
                    file.setLastModified(System.currentTimeMillis());//设置时间为了初始化时缓存排序
                    putCacheInfo(key, info);  //保存CachInfo到map中
                } catch (Exception e) {
                    boolean deleted = file.delete();
                    e.printStackTrace();
                } finally {
                    ...
                }
            }
        }

    以上就是DiskDataCacher主要的实现思路

    总结

    1. 通过以上源码分析,容易知道,在get put方法一定要在初始化方法(initialize())完成之后进行,因此,代码中使用了mLock.wait()和mLock.notifyAll()方法对此进行控制,initialize()方法最好在Application的onCreate中调用。
    2. 因为是磁盘缓存,当存储较大数据时,磁盘读写会比较耗时,因此需要在工作线程中执行,代码中已经封装好了一个工具DiskStringCacheManager,实现了对字符串的缓存以及线程池的封装。
    3. 需要缓存Bitmap或者JsonObject的话,只需要实现一个类似于DiskStringCacheManager的类,将String与byte[]的转换更改为Bitmap与byte[]的转换即可。当然,此处也有进一步的优化空间,可以将DiskStringCacheManager中String换成泛型,这样可以更容易扩展对其他类型数据的缓存。
    展开全文
  • PrimoCache是一款可以将物理内存、SSD硬盘或闪存盘等虚拟成硬盘缓存的软件。它可以自动将硬盘中读取的数据存入物理内存等速度较快的设备,当系统再次需要该数据时它可以很快从缓存设备中读取,而无需再次访问速度较...
  • PrimoCache是一款可以将物理内存、SSD硬盘或闪存盘等虚拟成硬盘缓存的软件。它可以自动将硬盘中读取的数据存入物理内存等速度较快的设备,当系统再次需要该数据时它可以很快从缓存设备中读取,而无需再次访问速度较...
  • 平时经常用到Volley请求网络数据,因为它确实好用,简单方便,因为项目要求也不是很苛刻,所以。。。。 呃。。。程序员总会去重构自己的代码,这不,我自己研究源码和网上的一些方法,...一:第一部分,实现内存缓存

    平时经常用到Volley请求网络数据,因为它确实好用,简单方便,因为项目要求也不是很苛刻,所以。。。。

    呃。。。程序员总会去重构自己的代码,这不,我自己研究源码和网上的一些方法,重构了自己方便用的代码,在这顺便记录一下。

    关于缓存,百度了好多,网上都是些什么研究源码的。。。呃,我想说,你们就别复制粘贴了,够多了!却很少有说这么用的。


    不多废话,正题。。。

    一:第一部分,实现内存缓存

    1.因为图片是很占内存的,一不小心就Boom。。。Boom。。。Boom了,下面是写一个图片内存缓存的类MImgCache.java ,看代码:

    import android.graphics.Bitmap;
    import android.util.LruCache;
    
    import com.android.volley.toolbox.ImageLoader;
    
    /**
     * Created by qinlang on 2015/10/21.
     */
    public class MImgCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {
        private static int MAX_SIZE = 10 * 1024 * 1024;//内存缓存大小,10M
    
        /**
         * @param maxSize for caches that do not override {@link #sizeOf}, this is
         *                the maximum number of entries in the cache. For all other caches,
         *                this is the maximum sum of the sizes of the entries in this cache.
         */
        public MImgCache(int maxSize) {
            super(maxSize);
        }
    
        public MImgCache() {
            this(MAX_SIZE);
        }
    
        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getRowBytes() * value.getHeight();
        }
    
        @Override
        public Bitmap getBitmap(String url) {
            return get(url);
        }
    
        @Override
        public void putBitmap(String url, Bitmap bitmap) {
            put(url, bitmap);
        }
    }
    代码很简单,就是使用LruCache,然后再指定内存大小什么的。

    2.接着自己写了一个工厂类VolleyFactroy.java,单例模式,目的是为了一个应用程序只能有一个请求队列:

    import android.content.Context;
    
    import com.android.volley.Request;
    import com.android.volley.RequestQueue;
    import com.android.volley.toolbox.Volley;
    
    /**
     * Created by qinlang on 2015/10/21.
     */
    public class VolleyFactroy {
        private RequestQueue requestQueue;
        private Context context;
        private MImgCache imgCache;
        private static final int MAX_DISK_CACHE = 20 * 1024 * 1024;//磁盘缓存20M
    
        private VolleyFactroy(Context context) {
            this.context = context;
            requestQueue = getRequestQueue();
            imgCache = new MImgCache();
        }
    
        private static VolleyFactroy instance;
    
        /**
         * 新的实例
         *
         * @param context
         * @return
         */
        public static synchronized VolleyFactroy getInstance(Context context) {
            if (instance == null)
                instance = new VolleyFactroy(context);
            return instance;
        }
    
        /**
         * 获取请求队列
         *
         * @return
         */
        public RequestQueue getRequestQueue() {
            if (requestQueue == null)
                requestQueue = Volley.newRequestQueue(context.getApplicationContext(),
                        MAX_DISK_CACHE);//实例一个请求队列,并初始化磁盘缓存大小
            return requestQueue;
        }
    
        /**
         * 添加下载队列
         *
         * @param request
         * @param <T>
         */
        public <T> void addRequest(Request<T> request) {
            getRequestQueue().add(request);
        }
    
        /**
         * 取消下载队列
         *
         * @param tag
         */
        public void cancelRequest(Object tag) {
            getRequestQueue().cancelAll(tag);
        }
    
        /**
         * 获取内存缓存对象
         *
         * @return
         */
        public MImgCache getImgCache() {
            return imgCache;
        }
    }

    呃。。。这样已经能使用内存缓存了,只要你用这个工厂类拿到的请求队列,图片加载什么的。。。还会那么容易OOM?。

    其实我也不知道这样写好不好,反正写着写着就变这样了,反正还蛮好用的,我也不保证完全正确。


    二:磁盘缓存部分(有三个决定因素)

    当然这里不只是磁盘缓存,因为你会发现上面的代码用起来很不方便,不是吗?下面我们再对上面进一步封装,

    让自己用起来so easy。。。

    这次我不写工厂类了,我写一个工具类。是的,没错,你们不也最喜欢工具类了?

    代码就懒得分了,全在下面,不难,该有注释的地方都有了,慢慢看。

    import android.app.Application;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.os.Handler;
    import android.os.Message;
    import android.text.TextUtils;
    import android.widget.ImageView;
    
    import com.android.volley.AuthFailureError;
    import com.android.volley.Cache;
    import com.android.volley.DefaultRetryPolicy;
    import com.android.volley.NetworkError;
    import com.android.volley.NoConnectionError;
    import com.android.volley.ParseError;
    import com.android.volley.Request;
    import com.android.volley.RequestQueue;
    import com.android.volley.Response;
    import com.android.volley.ServerError;
    import com.android.volley.TimeoutError;
    import com.android.volley.VolleyError;
    import com.android.volley.toolbox.DiskBasedCache;
    import com.android.volley.toolbox.ImageLoader;
    import com.android.volley.toolbox.StringRequest;
    import com.zzgx.warner.utils.Lg;
    
    import java.io.File;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Volley工具类
     *
     * @author Created by qinlang on 2016/3/3. last update at 2017.03
     */
    public class VolleyUtils {
        private static Context context;
        private static RequestQueue requestQueue;
        /**
         * 返回数据成功
         */
        public static final int RESULT_SUCCESS = 200;
        /**
         * 返回数据失败
         */
        public static final int RESULT_FAIL = 201;
        private static int timeOut = 10000;//超时时间
        public static final String TAG = "volley_requestQueue";
        private static final String DEFAULT_CACHE_DIR = "volley";//Volley默认缓存路径,不可更改
    
        private static VolleyFactroy volleyFactroy;
        private static VolleyUtils volleyUtils;
        private final File cacheDir;
        private static DiskBasedCache diskBasedCache;
        private static HashMap
      
        tagMap;
    
        public static VolleyUtils getInstance() {
            if (null == context) {
                throw new RuntimeException("Must be use init(context) in Application");
            }
            if (null == volleyUtils) {
                volleyUtils = new VolleyUtils(context);
            }
            return volleyUtils;
        }
    
        public static void init(Context context) {
            if (context == null) {
                throw new IllegalArgumentException("context can not be null");
            }
    
            if (!(context instanceof Application)) {
                throw new RuntimeException("context must be an Application Context");
            }
            VolleyUtils.context = context;
            volleyUtils = new VolleyUtils(context);
        }
    
        private VolleyUtils(Context context) {
            this.context = context;
            if (null == volleyFactroy)
                volleyFactroy = VolleyFactroy.getInstance(context);
            if (null == requestQueue)
                requestQueue = volleyFactroy.getRequestQueue();
            cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);//实例化缓存路径
            if (null == diskBasedCache)
                diskBasedCache = new DiskBasedCache(cacheDir);//实例化磁盘缓存类,用于清除缓存用
            if (null == tagMap)
                tagMap = new HashMap<>();
            tagMap.put(TAG, TAG);
        }
    
        /**
         * 发送Get请求
         *
         * @param url     请求url
         * @param handler 用于发回数据的handler,
         *                参数:what = {成功{@link #RESULT_SUCCESS}|失败{@link #RESULT_FAIL}},agr1 = {method},obj = {result}
         * @param method  用于判断哪个方法在调用
         */
        public void sendGetRequest(final String url, String tag, final Handler handler, final int method) {
            sendGetRequest(url, tag, new OnRequestResultListener() {
                @Override
                public void onResponse(String response) {
                    String jsonString = response.toString();
                    Message message = handler.obtainMessage();
                    message.what = RESULT_SUCCESS;
                    message.arg1 = method;
                    message.obj = jsonString;
                    handler.sendMessage(message);
                }
    
                @Override
                public void onErrorResponse(VolleyError error, String errString) {
                    error(error, handler, method);
                }
            });
        }
    
        /**
         * 发送GET请求
         *
         * @param url      请求url
         * @param listener 结果监听器
         */
        public void sendGetRequest(String url, String tag, final OnRequestResultListener listener) {
            if (TextUtils.isEmpty(tag)) tag = TAG;
            else cancleRequest(tag);
            tagMap.put(tag, tag);
    
            StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener
       
        () {
                @Override
                public void onResponse(String response) {
                    String jsonString = response.toString();
                    listener.onResponse(jsonString);
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    listener.onErrorResponse(error, error(error, null, 0));
                }
            });
            request.setShouldCache(true);
            request.setCacheEntry(new Cache.Entry());
            request.setTag(tag);//设置标签
            request.setRetryPolicy(new DefaultRetryPolicy(timeOut,
                    DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));//修改超时时间和重载次数
            requestQueue.add(request);
        }
    
        /**
         * 发送Post请求
         *
         * @param url     请求url
         * @param params  请求的参数集
         * @param handler 用于发回数据的handler,
         *                参数:what = {成功{@link #RESULT_SUCCESS}|失败{@link #RESULT_FAIL}},agr1 = {method},obj = {result}
         * @param method  用于判断哪个方法在调用
         */
        public void sendPostRequest(final String url, String tag, final HashMap
        
          params, final Handler handler, final int method) {
            sendPostRequest(url, tag, params, new OnRequestResultListener() {
                @Override
                public void onResponse(String response) {
                    String jsonString = response.toString();
                    Message message = handler.obtainMessage();
                    message.what = RESULT_SUCCESS;
                    message.arg1 = method;
                    message.obj = jsonString;
                    handler.sendMessage(message);
                }
    
                @Override
                public void onErrorResponse(VolleyError error, String errString) {
                    error(error, handler, method);
                }
            });
        }
    
        /**
         * 发送POST请求
         *
         * @param url      请求url
         * @param params   参数集
         * @param listener 结果监听器
         */
        public void sendPostRequest(String url, String tag, final HashMap
         
           params, final OnRequestResultListener listener) {
            if (TextUtils.isEmpty(tag)) tag = TAG;
            else cancleRequest(tag);
            tagMap.put(tag, tag);
    
            StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener
          
           () { @Override public void onResponse(String response) {//成功的请求结果 String jsonString = response.toString(); listener.onResponse(jsonString); } }, new Response.ErrorListener() {//失败的请求结果 @Override public void onErrorResponse(VolleyError error) { listener.onErrorResponse(error, error(error, null, 0)); } }) { @Override protected Map
           
             getParams() throws AuthFailureError { return params;//参数从这里进去 } /** * 设置头部信息 * @return * @throws AuthFailureError */ @Override public Map
            
              getHeaders() throws AuthFailureError { Map
             
               params = new HashMap
              
               (); params.put("Content-Type", "application/x-www-form-urlencoded");//发送的参数以表单形式 return params; } }; request.setShouldCache(true);//是否启用缓存,默认已经启用,可不用设置 request.setCacheEntry(new Cache.Entry());//设置缓存实体对象,注意:这里是重点,如果为null则不会有缓存 request.setTag(tag);//设置标签 request.setRetryPolicy(new DefaultRetryPolicy(timeOut, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));//修改超时时间和重载次数 requestQueue.add(request); } /** * 处理错误 * * @param error * @param handler * @param method */ private String error(VolleyError error, Handler handler, int method) { String err = "请求失败!"; if (error instanceof NetworkError) { err = "网络异常!"; } else if (error instanceof ServerError) { err = "系统繁忙!"; } else if (error instanceof AuthFailureError) { err = "请求验证失败!"; } else if (error instanceof ParseError) { err = "请求解析错误!"; } else if (error instanceof NoConnectionError) { err = "无法连接!"; } else if (error instanceof TimeoutError) { err = "请求超时!"; } if (null != handler) { Message message = handler.obtainMessage(); message.what = RESULT_FAIL; message.arg1 = method; message.obj = err; handler.sendMessage(message); } return err; } /** * 加载图片 * * @param url 图片url * @param result 回调,bitmap加载失败时为null */ public void loadImg(String url, final IBitmapResult result) { getImageLoader().get(url, new ImageLoader.ImageListener() { @Override public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) { Bitmap bitmap = response.getBitmap(); result.onResult(bitmap); } @Override public void onErrorResponse(VolleyError error) { result.onResult(null); } }); } /** * 加载图片 * * @param url 图片url * @param imageView * @param defaultImageResId 默认时显示的图片资源 * @param errorImageResId 加载错误时显示的图片资源 */ public void loadImg(String url, ImageView imageView, int defaultImageResId, int errorImageResId) { getImageLoader().get(url, ImageLoader.getImageListener(imageView, defaultImageResId, errorImageResId)); } /** * 移除指定缓存 * * @param method 方法名 请参阅{@link Request.Method},GET为0,POST为1;如此条数据用GET方式请求得到的,则参数为{@link Request.Method #GET} * @param url 请求url */ public void removeCache(Request.Method method, String url) { diskBasedCache.remove(method + ":" + url);//参数为key,默认:请求方法名+“:”+url } /** * 清除所有缓存 */ public void clearAllCache() { diskBasedCache.clear(); } /** * 设置超时时间,默认10s * * @param timeOut */ public void setTimeOut(int timeOut) { this.timeOut = timeOut; } /** * 取消全部请求 */ public void cancleAllRequest() { if (null != requestQueue && null != tagMap) { for (Map.Entry entry : tagMap.entrySet()) { requestQueue.cancelAll(entry.getValue()); } } } /** * 取消请求 * * @param tag tag */ public void cancleRequest(String tag) { if (null != tagMap) { if (!TextUtils.isEmpty(tag) && tagMap.containsKey(tag)) { requestQueue.cancelAll(tag); } } } /** * 获取请求队列 * * @return */ public RequestQueue getRequestQueue() { return requestQueue; } /** * 获取工厂类 * * @return */ public VolleyFactroy getVolleyFactroy() { return volleyFactroy; } /** * 获取ImageLoader * * @return */ public ImageLoader getImageLoader() { return new ImageLoader(requestQueue, volleyFactroy.getImgCache()); } /** * 请求结果监听器 */ public interface OnRequestResultListener { /** * 成功的请求 * * @param response 请求返回的字符串 */ void onResponse(String response); /** * 失败的请求 * * @param error * @param errString */ void onErrorResponse(VolleyError error, String errString); } /** * 加载图片的回调 */ public interface IBitmapResult { /** * 加载结果 * * @param bitmap */ void onResult(Bitmap bitmap); } } 
              
             
            
           
          
         
        
       
      
    这下是不是好用很多了,即可以发送GET请求,有可以发送POST请求,还实现了磁盘缓存。


    看代码,要实现磁盘缓存,你会发现里面有两个要点

    1.一个是是否可缓存,true为可缓存,false为不可缓存,其实volley内部已经默认缓存,所以这个不用理会都没事。啪。。。那你还说

    setShouldCache(true);
    2.设置缓存实体,如果为null,即传null给它或者不重写那个方法,则不会有缓存功能。这个是第二限制条件
    setCacheEntry(new Cache.Entry());


    等等。。。不是说有三个因素吗?怎么就见两个?别急,老大才是最后的:

    3.服务器端必须设置头部,告诉Volley这条数据是可以缓存的

    response.setHeader("cache-control", "public, max-age=43200");

    “缓存控制,公有(可以为私有),最大生命。。。”
    
    
    	没错,三个条件成立,volley才会自动帮您保存缓存,缓存也才会有效果。
    
    
    上面代码可能有点乱啊,其实清除缓存可以单独用的:
         private static final String DEFAULT_CACHE_DIR = "volley";//Volley默认缓存路径
         private DiskBasedCache diskBasedCache;
         
         if (null == diskBasedCache)
              diskBasedCache = new DiskBasedCache(cacheDir);//实例化磁盘缓存类,用于清除缓存用
         /**
         * 移除指定缓存
         *
         * @param method 方法名 请参阅{@link com.android.volley.Request.Method},GET为0,POST为1,其它方法请加对应的即可
         * @param url    请求url
         */
        public void removeCache(int method, String url) {
            if (method == Request.Method.GET)
                diskBasedCache.remove("0:" + url);//参数为key,默认为请求方法名+“:”+url
            else if (method == Request.Method.POST) diskBasedCache.remove("1:" + url);
        }
    
        /**
         * 清除所有缓存
         */
        public void clearAllCache() {
            diskBasedCache.clear();
        }

    到这就基本结束了。。。。本人用着感觉还很方便的,我们用volley无非就是发送一些简单的请求,
    用ImageLoader加载图片什么的(ImageLoader里面已经写好了,可直接拿去用)。
    
    
    	下面附加怎么用:
    发送GET/POST请求
    <pre name="code" class="html">HashMap<String, String> params = new HashMap<>();
    params.put("...", "...");
    
    //...
    <pre name="code" class="html"><pre name="code" class="html"><pre name="code" class="html">    private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                int what = msg.what;
                int method = msg.arg1;
                String result = (String) msg.obj;
                if (method == METHOD) {
    
                    if (what == VolleyUtils.RESULT_SUCCESS) {
                        
                    }else if(what == VolleyUtils.RESULT_FAIL){
    
    		}
                }
            }
        };
     
    
     
    
     
    
    VolleyUtils.getInstance(this).sendPostRequest(URL, params, handler, METHOD);
    GET请求还更简单,就不贴了。
    
    
    ImageLoader的使用
     
    
    ImageLoader imageLoader = VolleyUtils.getInstance(this).getImageLoader();
    imageLoader.get(imgUrl, ImageLoader.getImageListener(imageView, R.drawable.ic_default_avatar, R.drawable.ic_default_avatar));

    注意:清除缓存,因为可以单独使用,你那条数据用的什么方法请求就用什么方法的参数,
    如:用GET请求则volleyUtils.removeCache(0, url); GET的值为0。清除全部则顺便。
    
    
    
    最后,顺便说一下,写这些遇到的坑,因为网上都是那些七七八八的什么源码分析,一看就恼火,那时候没找到,然后还是看了好多,收货好多
    ,还是不行。不找了,然后看了一晚上的源码,自己找。再加网上的一些解释,最后还是弄好了,当时那个服务器加头部的网上找半天也没见有说。
    清除缓存也是,网上一点资料没擦边,还是看了一个多小时源码理清它的流程,找到方法的(其实也没那么难,但是网上就是没有),亲测清除成功。
    
    
    

    展开全文
  • 前言 顾名思义文件缓存内存缓存就是将存储在文件中的数据转到内存中去,实现磁盘操作转为内存操作,这样可以大大提高数据访问速度,并能实现缓存数据的分布式部署。文件缓存内存缓存的介绍请参考名词解释部分。 ...
  • CPU、缓存内存和本地磁盘的关系

    千次阅读 多人点赞 2018-07-10 14:20:09
    CPU CPU是中央处理器的简称,它可以从内存缓存中读取指令,放入指令寄存器,并能够发出控制指令来完成一条指令的执行。但是CPU并不能直接从硬盘中读取程序或数据。内存 内存作为与CPU直接进行沟通的部件,所有的...
  • 三分钟学会缓存工具DiskLruCache

    千次阅读 2015-08-04 19:02:02
    DiskLruCache是一个十分好用的android缓存工具,所有的数据都存储在/storage/emulated/0/Android/data/应用包名/cache/XXX文件夹中,这个是android系统默认的应用缓存位置,如果应用被删除,这个文件也会一起被删除...
  • CPU从存储器(内存Memory)或高速缓冲存储器(缓存Cache)中取出指令,放入指令寄存器,并对指令译码。它把指令分解成一系列的微操作,然后发出各种控制命令,执行微操作系列,从而完成一条指令的执行。 内存...
  • 缓存的数据在内存磁盘当中 缓存数据在虚拟机重启时写入磁盘 可以通过rmi和接口的方式实现分布式缓存 允许注册事件来侦听缓存 GuavaCache 相对于CurrentHashMap,限制内存的使用,会自动回收元素 轻量级框架 ...
  • CPU是中央处理器的简称,它可以从内存缓存中读取指令,放入指令寄存器,并能够发出控制指令来完成一条指令的执行。但是CPU并不能直接从硬盘中读取程序或数据。 内存 内存作为与CPU直接进行沟通的部件,所有的程序...
  • 虚拟内存与页面缓存

    千次阅读 2013-04-15 10:53:51
     操作系统会一次性读出磁盘上的内容,类似的虚拟内存机制给进程分配内存的时候也不是一个字节一个字节地访问,而是分配好适当的大小(4kb左右)并传递给进程。这样的一个内存块称为“页面”。进程要求分配内存时,
  • 顾名思义文件缓存内存缓存就是将存储在文件中的数据转到内存中去,实现磁盘操作转为内存操作,这样可以大大提高数据访问速度,并能实现缓存数据的分布式部署。文件缓存内存缓存的介绍请参考名词解释部分。 ...
  •  一个计算机包含多种存储器比如:寄存器、高速缓存内存硬盘、光盘等,为啥有这么多种存储方式,对于不太了解的人,总是觉得云里雾里的,搞不明白原因,直接弄一个存储器不就得了? 计算机主要的功能就是运算...
  • 实现图片最终页的浏览效果源码,源码Haneke,Haneke是一个简单易用的,适用于iOS 应用的零配置图片缓存工具。Haneke可调整图片大小,并把结果缓存在内存或者磁盘上,完全在后台完成,支持快速的响应式的页面滚动。 ...
  • 缓存文件过大会导致Sketch使用非常的卡,想要恢复你的mac硬盘空间,让您的Mac健步如飞就来看看Sketch缓存一键清理工具吧!这款Sketch 历史文件一键清理工具使用非常的简单哦,只需要几秒钟就能够为您清理掉占用硬盘...
  • 顾名思义文件缓存内存缓存就是将存储在文件中的数据转到内存中去,实现磁盘操作转为内存操作,这样可以大大提高数据访问速度,并能实现缓存数据的分布式部署。文件缓存内存缓存的介绍请参考名词解释部分。 ...
  • 最近负责公司项目中的图片和文件...LruCache是android提供的一个缓存工具,在Api 12上出现,在api12以下可以导入support v4包进行使用。android设备版本升级的速度还是太慢了啊。官方地址:https://developer.android.c

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 151,556
精华内容 60,622
关键字:

内存作为硬盘缓存工具