android中图片的三级cache策略(内存、文件、网络)之三:文件缓存策略

标签: 缓存 图片 文件
11037人阅读 评论(12) 收藏 举报
分类:

前言

如果想很好地理解下面的故事,请参看我半年前写的两篇博文:android中图片的三级cache策略(内存、文件、网络) 一 和 android中左右滑屏的实现(广告位banner组件),还有昨天晚上写的android中图片的三级cache策略(内存、文件、网络)之二:内存缓存策略

文件缓存策略

当一张图片从网络下载成功以后,这个图片会被加入内存缓存和文件缓存,对于文件缓存来说,这张图片将被以url的哈希值加cach后缀名的形式存储在SD卡上,这样,当下一次再需要同一个url的图片的时候,就不需要从网络下载了,而是直接通过url来进行查找。同时一张图片被访问时,它的最后修改时间将被更新,这样的意义在于:当SD卡空间不足的时候,将会按照最后修改时间来删除40%缓存的图片,确切来说,那些修改时间比较早的图片将会被删除。

代码展示

public class ImageFileCache
{
    private static final String TAG = "ImageFileCache";
	
    //图片缓存目录
    private static final String IMGCACHDIR = "/sdcard/ImgCach";
    
    //保存的cache文件宽展名
    private static final String CACHETAIL = ".cach";
                                                            
    private static final int MB = 1024*1024;
    
    private static final int CACHE_SIZE = 1;
    
    //当SD卡剩余空间小于10M的时候会清理缓存
    private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;
                                                                
    public ImageFileCache() 
    {
        //清理部分文件缓存
        removeCache(IMGCACHDIR);    		
    }
                                                                
    /** 
     * 从缓存中获取图片 
     */
    public Bitmap getImageFromFile(final String url) 
    {    
        final String path = IMGCACHDIR + "/" + convertUrlToFileName(url);
        File file = new File(path);
        if (file != null && file.exists()) 
        {
            Bitmap bmp = BitmapFactory.decodeFile(path);
            if (bmp == null) 
            {
                file.delete();
            } 
            else 
            {
                updateFileTime(path);
                Logger.d(TAG, "get bmp from FileCache,url=" + url);
                return bmp;
            }
        }
        return null;
    }
                                                                
    /**
     * 将图片存入文件缓存 
     */
    public void saveBitmapToFile(Bitmap bm, String url) 
    {
        if (bm == null) {
            return;
        }
        //判断sdcard上的空间
        if (FREE_SD_SPACE_NEEDED_TO_CACHE > SdCardFreeSpace()) 
        {
            //SD空间不足
            return;
        }
        
        String filename = convertUrlToFileName(url);
        File dirFile = new File(IMGCACHDIR);
        if (!dirFile.exists())
            dirFile.mkdirs();
        File file = new File(IMGCACHDIR +"/" + filename);
        try 
        {
            file.createNewFile();
            OutputStream outStream = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            outStream.flush();
            outStream.close();
        } 
        catch (FileNotFoundException e) 
        {
            Logger.d(TAG, "FileNotFoundException");
        } 
        catch (IOException e) 
        {
            Logger.d(TAG, "IOException");
        }
    } 
                                                                
    /**
     * 计算存储目录下的文件大小,
     * 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
     * 那么删除40%最近没有被使用的文件
     */
    private boolean removeCache(String dirPath) 
    {
        File dir = new File(dirPath);
        File[] files = dir.listFiles();
        
        if (files == null) 
        {
            return true;
        }
        
        if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
        {
            return false;
        }
                                                            
        int dirSize = 0;
        for (int i = 0; i < files.length; i++) 
        {
            if (files[i].getName().contains(CACHETAIL)) 
            {
                dirSize += files[i].length();
            }
        }
                                                            
        if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > SdCardFreeSpace()) 
        {
            int removeFactor = (int) (0.4 * files.length);
            Arrays.sort(files, new FileLastModifSort());
            for (int i = 0; i < removeFactor; i++) 
            {
                if (files[i].getName().contains(CACHETAIL)) 
                {
                    files[i].delete();
                }
            }
        }
                                                            
        if (SdCardFreeSpace() <= CACHE_SIZE) 
        {
            return false;
        }
                                                                    
        return true;
    }
                                                                
    /**
     * 修改文件的最后修改时间
     */
    public void updateFileTime(String path) 
    {
        File file = new File(path);
        long newModifiedTime = System.currentTimeMillis();
        file.setLastModified(newModifiedTime);
    }
                                                                
    /** 
     * 计算SD卡上的剩余空间 
     */
    private int SdCardFreeSpace()
    {
        StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
        return (int) sdFreeMB;
    } 
                                                                
    /** 
     * 将url转成文件名 
     */
    private String convertUrlToFileName(String url)
    {
    	return url.hashCode() + CACHETAIL;
    }
                                                                
    /**
     * 根据文件的最后修改时间进行排序
     */
    private class FileLastModifSort implements Comparator<File> 
    {
        public int compare(File file0, File file1) 
        {
            if (file0.lastModified() > file1.lastModified())
            {
                return 1;
            } 
            else if (file0.lastModified() == file1.lastModified()) 
            {
                return 0;
            } 
            else 
            {
                return -1;
            }
        }
    }

}

说明:上述代码很好理解而且都有注释,不用多说了。

到这里,整个banner体系的代码都被介绍了,希望代码中的思想能够对大家有所启发,谢谢大家的捧场!

查看评论

Glide图片框架使用详细介绍(二)之缓存策略

一、 上篇文章我们了解到 Glide的基本使用很简单,且可配置度高 http://blog.csdn.net/qq_37237245/article/details/72956121 Gl...
  • qq_37237245
  • qq_37237245
  • 2017-06-09 12:26:18
  • 611

图片的三级缓存cache策略

android中图片的三级缓存cache策略(内存/文件/网络) 实现图片缓存也不难,需要有相应的cache策略。这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和...
  • u011682673
  • u011682673
  • 2016-08-03 20:44:03
  • 464

Android中图片的三级缓存(内存、文件、网络)

最近项目中图片太多起初只做了二级缓存(其实就是做了一个文件缓存)但是总感觉不够好,于是就研究了一下三级缓存并用到项目中。下面就谈谈三级缓存吧。1、为什么要使用三级缓存 如今的 Android App ...
  • Army_Jun
  • Army_Jun
  • 2016-12-01 19:05:40
  • 2506

android中图片的三级cache策略(内存、文件、网络)之三:文件缓存策略 .

文件缓存策略 当一张图片从网络下载成功以后,这个图片会被加入内存缓存和文件缓存,对于文件缓存来说,这张图片将被以url的哈希值加cach后缀名的形式存储在SD卡上,这样,当下一次再需要同一个url的...
  • zml_2015
  • zml_2015
  • 2015-10-25 21:32:10
  • 1318

安卓图片三级缓存策略与实现

前言: 这里说的三级缓存,分别指的是:内存缓存、文件缓存和网络这三个层面。 一般来说,我们首次加载图片,内存和文件是没有缓存的,这样我们需要从网络加载,加载完成后,我们会存到内存和文件中去;当再次加载...
  • u010335298
  • u010335298
  • 2016-08-18 19:26:08
  • 3500

Android中图片的三级缓存策略

一、简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好。所以一个应用的图片缓存策...
  • qq_20889581
  • qq_20889581
  • 2016-04-01 11:15:53
  • 3132

图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)

在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量。对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理...
  • jie1991liu
  • jie1991liu
  • 2015-07-17 13:59:49
  • 3881

glide的缓存策略

本文主要介绍了如何配置和管理Glide中的缓存,其中大部分内容都可以直接在官方Wiki中找到,这里只是进行了整理和汇总。言归正传,Glide支持图片的二级缓存(并不是三级缓存,因为从网络加载并不属于缓...
  • shangming150
  • shangming150
  • 2017-09-04 16:35:31
  • 235

【安卓中的缓存策略系列】安卓缓存之内存缓存LruCache

缓存策略在移动端设备上是非常重要的,尤其是在图片加载这个场景下,因为图片相对而言比较大会花费用户较多的流量,因此可用缓存方式来解决,即当程序第一次从网络上获取图片的时候,就将其缓存到存储设备上,这样在...
  • htq__
  • htq__
  • 2016-05-11 21:04:58
  • 6461

Android中图片的三级cache策略(内存、文件、网络)

http://blog.csdn.net/cuijinquan/article/details/17688615 http://blog.csdn.net/cuijinquan/articl...
  • han_jiang_xue
  • han_jiang_xue
  • 2014-01-14 18:53:58
  • 844
    我的书
    Android art
    Amazon     京东     当当

    公众号
    聚焦于『Android开发前沿、AI技术、职业发展、生活感悟、妹子图』,欢迎大家关注。
    QQ交流群:635778578
    个人资料
    专栏达人 博客之星
    等级:
    访问量: 202万+
    积分: 1万+
    排名: 761
    博客专栏
    最新评论